Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 | 1x 35x 35x 35x 35x 35x 35x 35x 35x 35x 35x 35x 35x 66x 28x 3x 3x 1x 89x 89x 28x 28x 2x 94x 94x | /**
* Copyright (c) Siemens 2016 - 2025
* SPDX-License-Identifier: MIT
*/
import { FocusMonitor } from '@angular/cdk/a11y';
import {
AfterContentInit,
ChangeDetectionStrategy,
Component,
contentChild,
DestroyRef,
DoCheck,
ElementRef,
inject,
input,
OnInit,
signal,
viewChild
} from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { NgControl } from '@angular/forms';
import { addIcons, elementCalendar, SiIconComponent } from '@siemens/element-ng/icon';
import { SiTranslatePipe, t } from '@siemens/element-translate-ng/translate';
import { SiDatepickerOverlayDirective } from './si-datepicker-overlay.directive';
import { SiDatepickerDirective } from './si-datepicker.directive';
/**
* Calendar toggle button used in combination with a datepicker directive.
*
* @example
* ```
* <si-calendar-button class="w-100">
* <input
* class="form-control"
* type="text"
* siDatepicker
* [siDatepickerConfig]="config"
* />
* </si-calendar-button>
* ```
*/
@Component({
selector: 'si-calendar-button',
imports: [SiIconComponent, SiTranslatePipe],
template: `<ng-content />
<button
#calendarButton
name="open-calendar"
type="button"
class="btn btn-circle btn-tertiary btn-xs position-absolute end-0 top-0 me-2 mt-2"
[attr.aria-label]="ariaLabel() | translate"
[disabled]="disabled()"
(click)="show()"
>
<si-icon [icon]="icons.elementCalendar" />
</button>`,
styles: ':host {--si-action-icon-offset: 24px;}',
changeDetection: ChangeDetectionStrategy.OnPush,
host: {
class: 'd-inline-block position-relative form-control-wrapper',
'[class.ng-invalid]': 'showValidationMessages()',
'[class.ng-touched]': 'showValidationMessages()'
}
})
export class SiCalendarButtonComponent implements OnInit, AfterContentInit, DoCheck {
/**
* Aria label for the calendar toggle button.
*
* @defaultValue
* ```
* t(() => $localize`:@@SI_DATEPICKER.CALENDAR_TOGGLE_BUTTON:Open calendar`)
* ```
*/
readonly ariaLabel = input(
t(() => $localize`:@@SI_DATEPICKER.CALENDAR_TOGGLE_BUTTON:Open calendar`)
);
protected readonly button = viewChild.required<ElementRef<HTMLButtonElement>>('calendarButton');
/** Datepicker input directive instance used to watch for state changes and required to open the calendar. */
protected readonly datepicker = contentChild.required(SiDatepickerDirective);
protected readonly datepickerOverlay = contentChild.required(SiDatepickerOverlayDirective);
protected readonly ngControl = contentChild(NgControl);
protected readonly disabled = signal(false);
protected readonly icons = addIcons({ elementCalendar });
private readonly destroyerRef = inject(DestroyRef);
private readonly focusMonitor = inject(FocusMonitor);
private readonly elementRef = inject<ElementRef<HTMLElement>>(ElementRef);
// Add classes here to enable error messages in si-form-item
protected readonly showValidationMessages = signal(false);
ngOnInit(): void {
// Monitor input state changes and update the button accordingly
this.datepicker().stateChange.subscribe(() => this.updateState());
this.focusMonitor
.monitor(this.elementRef, true)
.pipe(takeUntilDestroyed(this.destroyerRef))
.subscribe(origin => {
setTimeout(() => {
if (origin === null && !this.datepickerOverlay().isShown()) {
this.datepicker().touch();
}
});
});
}
ngDoCheck(): void {
const control = this.ngControl()?.control;
this.showValidationMessages.set(!!control?.touched && !!control?.invalid);
}
ngAfterContentInit(): void {
this.datepicker().useExternalTrigger(this.button());
this.updateState();
}
protected show(): void {
this.datepicker().show(true);
}
private updateState(): void {
const datepicker = this.datepicker();
this.disabled.set(datepicker.disabled() || datepicker.readonly());
}
}
|