Skip to content

Commit d707ab2

Browse files
committed
refactor(date-picker): enhance reactive form synchronization with properties panel
1 parent 3b520ad commit d707ab2

File tree

1 file changed

+47
-11
lines changed

1 file changed

+47
-11
lines changed

src/app/date-picker/date-picker.sample.ts

Lines changed: 47 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ export class DatePickerSampleComponent {
161161
type: 'text'
162162
}
163163
}
164-
}
164+
};
165165

166166
public properties: Properties = Object.fromEntries(
167167
Object.keys(this.panelConfig).map((key) => {
@@ -170,8 +170,9 @@ export class DatePickerSampleComponent {
170170
})
171171
) as Properties;
172172

173+
// FormControl owns the date picker value
173174
public reactiveForm = this.fb.group({
174-
datePicker: [this.properties?.value || ''],
175+
datePicker: [null],
175176
});
176177

177178
constructor() {
@@ -181,21 +182,56 @@ export class DatePickerSampleComponent {
181182
this.propertyChangeService.propertyChanges.subscribe(
182183
(properties) => {
183184
this.properties = properties;
184-
this.reactiveForm.patchValue({
185-
datePicker: properties?.value || ''
186-
});
187-
this.updateRequiredValidator();
185+
this.syncFormControlFromProperties();
188186
}
189187
);
190188

191189
this.destroyRef.onDestroy(() => propertyChange.unsubscribe());
192190
}
193191

194-
private updateRequiredValidator(): void {
192+
/**
193+
* Syncs the reactive form control with the properties panel:
194+
* - programmatic value updates
195+
* - required validator
196+
* - disabled state
197+
*
198+
* All done in a way that does NOT mark the control dirty/touched.
199+
*/
200+
private syncFormControlFromProperties(): void {
195201
const control = this.reactiveForm.get('datePicker');
196-
if (control) {
197-
control.setValidators(this.properties?.required ? Validators.required : null);
198-
control.updateValueAndValidity();
202+
if (!control) {
203+
return;
204+
}
205+
206+
// 1) Programmatic value update (from properties.value)
207+
// This does NOT mark the control dirty/touched.
208+
if ('value' in this.properties) {
209+
const newValue = this.properties.value ?? null;
210+
const currentValue = control.value;
211+
212+
// Shallow equality check to avoid unnecessary writes
213+
const sameValue =
214+
(newValue === currentValue) ||
215+
(newValue instanceof Date &&
216+
currentValue instanceof Date &&
217+
newValue.getTime() === currentValue.getTime());
218+
219+
if (!sameValue) {
220+
control.setValue(newValue, { emitEvent: false });
221+
}
222+
}
223+
224+
// 2) Required validator
225+
control.setValidators(this.properties?.required ? Validators.required : null);
226+
// This will trigger statusChanges, but control is still pristine/untouched,
227+
// so IgxDatePicker will keep the visual state INITIAL until user interaction.
228+
control.updateValueAndValidity();
229+
230+
// 3) Disabled state
231+
if (this.properties?.disabled) {
232+
control.disable({ emitEvent: false });
233+
} else {
234+
control.enable({ emitEvent: false });
199235
}
200236
}
201237

@@ -206,7 +242,7 @@ export class DatePickerSampleComponent {
206242
: PickerInteractionMode.Dialog;
207243
}
208244

209-
protected selectToday(picker) {
245+
protected selectToday(picker: { value: Date; hide: () => void }) {
210246
picker.value = new Date();
211247
picker.hide();
212248
}

0 commit comments

Comments
 (0)