diff --git a/api-goldens/element-ng/datepicker/index.api.md b/api-goldens/element-ng/datepicker/index.api.md index 8dc0e6af8c..0d5855b30d 100644 --- a/api-goldens/element-ng/datepicker/index.api.md +++ b/api-goldens/element-ng/datepicker/index.api.md @@ -396,6 +396,8 @@ export class SiDateRangeComponent implements ControlValueAccessor, Validator, Af // (undocumented) registerOnTouched(fn: () => void): void; // (undocumented) + registerOnValidatorChange(fn: () => void): void; + // (undocumented) setDisabledState(isDisabled: boolean): void; readonly siDatepickerConfig: _angular_core.ModelSignal; readonly siDatepickerRangeChange: _angular_core.OutputEmitterRef; diff --git a/projects/element-ng/datepicker/si-date-range.component.spec.ts b/projects/element-ng/datepicker/si-date-range.component.spec.ts index 2f85920936..8b25864d3b 100644 --- a/projects/element-ng/datepicker/si-date-range.component.spec.ts +++ b/projects/element-ng/datepicker/si-date-range.component.spec.ts @@ -7,6 +7,7 @@ import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed'; import { Component, signal, viewChild } from '@angular/core'; import { ComponentFixture, TestBed } from '@angular/core/testing'; import { FormControl, FormGroup, FormsModule, ReactiveFormsModule } from '@angular/forms'; +import { form, FormField } from '@angular/forms/signals'; import { DatepickerInputConfig, @@ -243,6 +244,36 @@ class FormWrapperComponent { readonly siDateRangeComponent = viewChild.required(SiDateRangeComponent); } + +@Component({ + imports: [FormField, SiDateRangeComponent], + template: `` +}) +class SignalFormWrapperComponent { + readonly model = signal<{ dateRange: DateRange }>({ + dateRange: { start: undefined, end: undefined } + }); + readonly form = form(this.model); +} + +describe('SiDateRangeComponent with a signal form field', () => { + it('should expose invalid start date format errors', async () => { + const fixture = TestBed.createComponent(SignalFormWrapperComponent); + await fixture.whenStable(); + + enterValue(startInput(fixture.nativeElement), 'INVALID DATE'); + startInput(fixture.nativeElement).dispatchEvent(new Event('input')); + await fixture.whenStable(); + + expect(fixture.componentInstance.form.dateRange().errors()).toEqual([ + expect.objectContaining({ kind: 'invalidStartDateFormat' }) + ]); + }); +}); + describe('SiDateRangeComponent within form', () => { let fixture: ComponentFixture; let component: FormWrapperComponent; diff --git a/projects/element-ng/datepicker/si-date-range.component.ts b/projects/element-ng/datepicker/si-date-range.component.ts index 94c51ae511..5891f3f9bc 100644 --- a/projects/element-ng/datepicker/si-date-range.component.ts +++ b/projects/element-ng/datepicker/si-date-range.component.ts @@ -227,6 +227,7 @@ export class SiDateRangeComponent private validator!: ValidatorFn; private onChange = (val: any): void => {}; private onTouch = (): void => {}; + private onValidatorChange = (): void => {}; protected readonly icons = addIcons({ elementCalendar }); protected readonly disabled = computed(() => this.disabledInput() || this.disabledNgControl()); @@ -291,6 +292,10 @@ export class SiDateRangeComponent this.onTouch = fn; } + registerOnValidatorChange(fn: () => void): void { + this.onValidatorChange = fn; + } + setDisabledState(isDisabled: boolean): void { this.disabledNgControl.set(isDisabled); } @@ -321,6 +326,7 @@ export class SiDateRangeComponent this.updateValue(dateRange); this.onChange(this.value()); + this.onValidatorChange(); this.siDatepickerRangeChange.emit(this.value()); }