Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
# Changelog
All notable changes to this project will be documented in this file.

# [22.1.0] (2026-09-21)

### Bug Fixes
- Support initial values and validator updates when the picker is used with Angular Signal Forms.
Comment thread
vlio20 marked this conversation as resolved.
Outdated

# [22.0.0] (2026-09-19)

### Improvements
Expand Down
2 changes: 1 addition & 1 deletion projects/ng2-date-picker/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ng2-date-picker",
"version": "22.0.0",
"version": "22.1.0",
"author": "Vlad Ioffe",
"license": "MIT",
"repository": {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import {Component, signal} from '@angular/core';
import {FormsModule} from '@angular/forms';
import {form, FormField} from '@angular/forms/signals';
import {DatePickerComponent} from './date-picker.component';
import {DayTimeCalendarComponent} from '../day-time-calendar/day-time-calendar.component';
import {DayTimeCalendarService} from '../day-time-calendar/day-time-calendar.service';
Expand All @@ -14,6 +16,16 @@ import {UtilsService} from '../common/services/utils/utils.service';
import {By} from '@angular/platform-browser';
import {OverlayModule} from '@angular/cdk/overlay';

@Component({
standalone: false,
template: '<dp-date-picker [config]="config" [formField]="dateForm.date"></dp-date-picker>'
})
class SignalFormDatePickerHostComponent {
readonly config = {format: 'YYYY-MM-DD'};
readonly model = signal({date: '2026-09-21'});
readonly dateForm = form(this.model);
}

describe('Component: DatePickerComponent', () => {
let component: DatePickerComponent;
let fixture: ComponentFixture<DatePickerComponent>;
Expand All @@ -26,8 +38,9 @@ describe('Component: DatePickerComponent', () => {

beforeEach(() => {
TestBed.configureTestingModule({
imports: [FormsModule, OverlayModule],
imports: [FormsModule, OverlayModule, FormField],
declarations: [
SignalFormDatePickerHostComponent,
DatePickerComponent,
DayTimeCalendarComponent,
DayCalendarComponent,
Expand All @@ -54,6 +67,17 @@ describe('Component: DatePickerComponent', () => {
expect(component).toBeTruthy();
});

it('should render an initial value when bound through Signal Forms', () => {
const signalFormFixture = TestBed.createComponent(SignalFormDatePickerHostComponent);

expect(() => signalFormFixture.detectChanges()).not.toThrow();

const datePicker = signalFormFixture.debugElement.query(By.directive(DatePickerComponent))
.componentInstance as DatePickerComponent;
expect(datePicker.selected[0].format('YYYY-MM-DD')).toBe('2026-09-21');
expect(signalFormFixture.componentInstance.model().date).toBe('2026-09-21');
});

it('should emit event goToCurrent when day calendar emit', () => {
setComponentMode('day');
component.showCalendars();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,8 @@ export class DatePickerComponent implements OnChanges,
handleInnerElementClickUnlisteners: Function[] = [];
globalListenersUnlisteners: Function[] = [];
validateFn: DateValidator;
private isWritingValue = false;
private onValidatorChange: () => void;
api: IDpDayPickerApi = {
open: this.showCalendars.bind(this),
close: this.hideCalendar.bind(this),
Expand Down Expand Up @@ -157,7 +159,9 @@ export class DatePickerComponent implements OnChanges,
.convertFromDayjsArray(this.componentConfig.format, selected, ECalendarValue.StringArr))
.join(' | ');
const val = this.processOnChangeCallback(selected);
this.onChangeCallback(val, false);
if (!this.isWritingValue) {
this.onChangeCallback(val, false);
}
this.onChange.emit(val);
}

Expand Down Expand Up @@ -212,12 +216,19 @@ export class DatePickerComponent implements OnChanges,
writeValue(value: CalendarValue): void {
this.inputValue = value;

if (value || value === '') {
this.selected = this.utilsService
.convertToDayjsArray(value, this.componentConfig);
this.init();
} else {
this.selected = [];
this.isWritingValue = true;
try {
this.componentConfig ??= this.dayPickerService.getConfig(this.config, this.mode);

if (value || value === '') {
this.selected = this.utilsService
.convertToDayjsArray(value, this.componentConfig);
this.init();
} else {
this.selected = [];
}
} finally {
this.isWritingValue = false;
}

this.cd.markForCheck();
Expand All @@ -237,6 +248,10 @@ export class DatePickerComponent implements OnChanges,
onTouchedCallback() {
}

registerOnValidatorChange(fn: () => void): void {
this.onValidatorChange = fn;
}

validate(formControl: UntypedFormControl): ValidationErrors {
return this.validateFn(formControl.value);
}
Expand All @@ -262,7 +277,7 @@ export class DatePickerComponent implements OnChanges,
maxTime: this.maxTime
}, this.componentConfig.format, this.mode);

this.onChangeCallback(this.processOnChangeCallback(this.selected), false);
this.onValidatorChange?.();
}

ngOnInit(): void {
Expand Down
Loading