@@ -28,7 +28,8 @@ import { CUSTOM_MOMENT_FORMATS } from './datetime-picker-utils';
2828 useClass : NgxMatMomentAdapter ,
2929 deps : [ MAT_LEGACY_DATE_LOCALE , NGX_MAT_MOMENT_DATE_ADAPTER_OPTIONS ]
3030 } ,
31- { provide : NGX_MAT_MOMENT_DATE_ADAPTER_OPTIONS , useValue : { useUtc : true } }
31+ // { provide: NGX_MAT_MOMENT_DATE_ADAPTER_OPTIONS, useValue: { useUtc: true } }
32+ { provide : NGX_MAT_MOMENT_DATE_ADAPTER_OPTIONS , useValue : { useUtc : false } }
3233 ]
3334} )
3435
@@ -58,6 +59,8 @@ export class DatetimePickerComponent extends AbstractFormFieldComponent implemen
5859
5960 @Input ( ) public dateControl : FormControl = new FormControl ( new Date ( ) ) ;
6061
62+ public localDisplayControl : FormControl ;
63+
6164 private minimumDate = new Date ( '01/01/1800' ) ;
6265 private maximumDate = null ;
6366 private momentFormat = 'YYYY-MM-DDTHH:mm:ss.SSS' ;
@@ -70,21 +73,67 @@ export class DatetimePickerComponent extends AbstractFormFieldComponent implemen
7073 public ngOnInit ( ) : void {
7174 this . dateTimeEntryFormat = this . formatTranslationService . showOnlyDates ( this . caseField . dateTimeEntryFormat ) ;
7275 this . configureDatePicker ( this . dateTimeEntryFormat ) ;
73- // set date control based on mandatory field
76+
77+ const existingControl = ( this . parent || this . formGroup ) ?. controls ?. [ this . caseField . id ] ;
78+ console . log ( '[DatetimePicker] ngOnInit for field:' , this . caseField . id ) ;
79+ console . log ( '[DatetimePicker] caseField.value:' , this . caseField . value ) ;
80+ console . log ( '[DatetimePicker] existingControl exists:' , ! ! existingControl ) ;
81+ console . log ( '[DatetimePicker] existingControl.value:' , existingControl ?. value ) ;
82+
83+ // register the main control with parent form (will return existing control if present)
84+ // for when we're navigating back to an existing form
7485 this . dateControl = ( this . caseField . isMandatory ?
7586 this . registerControl ( new FormControl ( this . caseField . value || '' , [ Validators . required ] ) )
7687 : this . registerControl ( new FormControl ( this . caseField . value ) ) ) as FormControl ;
88+
89+ console . log ( '[DatetimePicker] After registerControl, dateControl.value:' , this . dateControl . value ) ;
90+
91+ // after registerControl, use dateControl.value as the source of truth
92+ // (it will have the existing value if navigating back, or caseField.value if new)
93+ let initialUtcValue = this . dateControl . value ;
94+ let initialLocalValue : string ;
95+
96+ // for DateTime fields, convert UTC to local for display
97+ if ( initialUtcValue && this . caseField . field_type . type === 'DateTime' ) {
98+ const utcMoment = moment . utc ( initialUtcValue ) ;
99+ const localMoment = utcMoment . local ( ) ;
100+ initialLocalValue = localMoment . format ( 'YYYY-MM-DDTHH:mm:ss.SSS' ) ;
101+ console . log ( '[DatetimePicker] Converted UTC to local:' , initialUtcValue , '->' , initialLocalValue ) ;
102+ } else {
103+ initialLocalValue = initialUtcValue || '' ;
104+ }
105+
106+ // create local display control with correct initial value
107+ this . localDisplayControl = new FormControl ( initialLocalValue ) ;
108+ console . log ( '[DatetimePicker] localDisplayControl initialized with:' , initialLocalValue ) ;
109+
110+ // sync local display control to main control with UTC conversion
111+ this . localDisplayControl . valueChanges . subscribe ( localValue => {
112+ if ( this . caseField . field_type . type === 'DateTime' && localValue ) {
113+ const parsedLocal = moment ( localValue , this . momentFormat ) ;
114+ if ( parsedLocal . isValid ( ) ) {
115+ const utcValue = parsedLocal . utc ( ) . format ( this . momentFormat ) ;
116+ this . dateControl . setValue ( utcValue , { emitEvent : false } ) ;
117+ } else {
118+ this . dateControl . setValue ( localValue , { emitEvent : false } ) ;
119+ }
120+ } else {
121+ this . dateControl . setValue ( localValue , { emitEvent : false } ) ;
122+ }
123+ } ) ;
124+
125+ // sync validation errors from local control to main control
126+ this . localDisplayControl . statusChanges . subscribe ( ( ) => {
127+ this . minError = this . localDisplayControl . hasError ( 'matDatetimePickerMin' ) ;
128+ this . maxError = this . localDisplayControl . hasError ( 'matDatetimePickerMax' ) ;
129+ } ) ;
130+
77131 // in resetting the format just after the page initialises, the input can be reformatted
78132 // otherwise the last format given will be how the text shown will be displayed
79133 setTimeout ( ( ) => {
80134 this . setDateTimeFormat ( ) ;
81135 this . formatValueAndSetErrors ( ) ;
82136 } , 1000 ) ;
83- // when the status changes check that the maximum/minimum date has not been exceeded
84- this . dateControl . statusChanges . subscribe ( ( ) => {
85- this . minError = this . dateControl . hasError ( 'matDatetimePickerMin' ) ;
86- this . maxError = this . dateControl . hasError ( 'matDatetimePickerMax' ) ;
87- } ) ;
88137 }
89138
90139 public setDateTimeFormat ( ) : void {
@@ -182,16 +231,16 @@ export class DatetimePickerComponent extends AbstractFormFieldComponent implemen
182231
183232 public yearSelected ( event : Moment ) : void {
184233 if ( this . startView === 'multi-year' && this . yearSelection ) {
185- this . dateControl . patchValue ( event . toISOString ( ) ) ;
234+ this . localDisplayControl . patchValue ( event . toISOString ( ) ) ;
186235 this . datetimePicker . close ( ) ;
187236 this . valueChanged ( ) ;
188237 }
189238 }
190239
191240 public monthSelected ( event : Moment ) : void {
192241 if ( this . startView === 'multi-year' ) {
193- this . dateControl . patchValue ( event . toISOString ( ) ) ;
194- this . dateControl . patchValue ( event . toISOString ( ) ) ;
242+ this . localDisplayControl . patchValue ( event . toISOString ( ) ) ;
243+ this . localDisplayControl . patchValue ( event . toISOString ( ) ) ;
195244 this . datetimePicker . close ( ) ;
196245 this . valueChanged ( ) ;
197246 }
@@ -200,19 +249,38 @@ export class DatetimePickerComponent extends AbstractFormFieldComponent implemen
200249 private formatValueAndSetErrors ( ) : void {
201250 if ( this . inputElement . nativeElement . value ) {
202251 let formValue = this . inputElement . nativeElement . value ;
203- formValue = moment ( formValue , this . dateTimeEntryFormat ) . format ( this . momentFormat ) ;
204- if ( formValue !== 'Invalid date' ) {
205- // if not invalid set the value as the formatted value
206- this . dateControl . setValue ( formValue ) ;
252+ const parsedMoment = moment ( formValue , this . dateTimeEntryFormat ) ;
253+
254+ if ( parsedMoment . isValid ( ) ) {
255+ // format the value in local time
256+ // localDisplayControl will auto-sync to dateControl with UTC conversion
257+ formValue = parsedMoment . format ( this . momentFormat ) ;
258+ this . localDisplayControl . setValue ( formValue ) ;
207259 } else {
208260 // ensure that the datepicker picks up the invalid error
209261 const keepErrorText = this . inputElement . nativeElement . value ;
262+ this . localDisplayControl . setValue ( keepErrorText ) ;
210263 this . dateControl . setValue ( keepErrorText ) ;
211264 this . inputElement . nativeElement . value = keepErrorText ;
212265 }
213266 } else {
214- // ensure required errors are picked up if relevant
215- this . dateControl . setValue ( '' ) ;
267+ // input is empty - check if we need to sync from control values
268+ if ( this . localDisplayControl . value ) {
269+ // control has a value but input doesn't - this happens when navigating back
270+ // manually sync the control value to the input element
271+ console . log ( '[DatetimePicker] formatValueAndSetErrors: Input empty but control has value, syncing:' , this . localDisplayControl . value ) ;
272+ const controlValue = this . localDisplayControl . value ;
273+ const parsedMoment = moment ( controlValue , this . momentFormat ) ;
274+ if ( parsedMoment . isValid ( ) ) {
275+ // format according to the display format and update the input
276+ const formattedValue = parsedMoment . format ( this . dateTimeEntryFormat ) ;
277+ this . inputElement . nativeElement . value = formattedValue ;
278+ console . log ( '[DatetimePicker] Set input value to:' , formattedValue ) ;
279+ }
280+ } else if ( ! this . dateControl . value ) {
281+ this . localDisplayControl . setValue ( '' ) ;
282+ this . dateControl . setValue ( '' ) ;
283+ }
216284 }
217285 }
218286}
0 commit comments