diff --git a/lib/core/src/lib/form/components/widgets/core/form-field-validator.ts b/lib/core/src/lib/form/components/widgets/core/form-field-validator.ts index ce097b7dd84..e3b763d9925 100644 --- a/lib/core/src/lib/form/components/widgets/core/form-field-validator.ts +++ b/lib/core/src/lib/form/components/widgets/core/form-field-validator.ts @@ -132,6 +132,7 @@ export class DateFieldValidator implements FormFieldValidator { // Validates that the input string is a valid date formatted as (default D-M-YYYY) static isValidDate(inputDate: string, dateFormat: string = 'D-M-YYYY'): boolean { + // debugger; return DateFnsUtils.isValidDate(inputDate, dateFormat); } diff --git a/lib/core/src/lib/form/components/widgets/core/form-field.model.ts b/lib/core/src/lib/form/components/widgets/core/form-field.model.ts index aae980098a7..4ff82d588a6 100644 --- a/lib/core/src/lib/form/components/widgets/core/form-field.model.ts +++ b/lib/core/src/lib/form/components/widgets/core/form-field.model.ts @@ -358,6 +358,7 @@ export class FormFieldModel extends FormWidgetModel { if (isNumberValue(value)) { dateValue = new Date(value); } else { + // debugger; dateValue = this.isDateTimeField(json) ? DateFnsUtils.parseDate(value, 'YYYY-MM-DD hh:mm A') : DateFnsUtils.parseDate(value.split('T')[0], 'YYYY-M-D'); diff --git a/lib/core/src/lib/form/components/widgets/date-time/date-time.widget.html b/lib/core/src/lib/form/components/widgets/date-time/date-time.widget.html index fed0a6edc8f..393e65c3ff7 100644 --- a/lib/core/src/lib/form/components/widgets/date-time/date-time.widget.html +++ b/lib/core/src/lib/form/components/widgets/date-time/date-time.widget.html @@ -17,11 +17,7 @@ { expect(widget.maxDate.toISOString()).toBe('1982-03-13T10:00:00.000Z'); }); - it('should eval visibility on date changed', () => { + it('should eval visibility on date changed', async () => { spyOn(widget, 'onFieldChanged').and.callThrough(); const field = new FormFieldModel(form, { @@ -100,7 +100,11 @@ describe('DateTimeWidgetComponent', () => { }); widget.field = field; - widget.onDateChanged({ value: new Date('1982-03-13T10:00:00.000Z') } as any); + + fixture.detectChanges(); + await fixture.whenStable(); + + widget.datetimeInputControl.setValue(new Date('1982-03-13T10:00:00.000Z')); expect(widget.onFieldChanged).toHaveBeenCalledWith(field); }); @@ -115,7 +119,7 @@ describe('DateTimeWidgetComponent', () => { widget.field = field; - fixture.whenStable(); + fixture.detectChanges(); await fixture.whenStable(); expect(field.isValid).toBeTrue(); @@ -131,12 +135,12 @@ describe('DateTimeWidgetComponent', () => { widget.field = field; - fixture.whenStable(); + fixture.detectChanges(); await fixture.whenStable(); - widget.onDateChanged({ value: new Date('9999-09-12T09:10:00.000Z') } as any); + widget.datetimeInputControl.setValue(new Date('9999-09-12T09:10:00.000Z')); - expect(field.value).toBe('9999-09-12T09:10:00.000Z'); + expect(field.value).toEqual(new Date('9999-09-12T09:10:00.000Z')); expect(field.isValid).toBeTrue(); }); @@ -153,19 +157,15 @@ describe('DateTimeWidgetComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - widget.onDateChanged({ - value: null, - targetElement: { - value: '123abc' - } - } as any); + widget.datetimeInputControl.setValue('123abc'); fixture.detectChanges(); await fixture.whenStable(); - expect(field.value).toBe('123abc'); - expect(field.isValid).toBeFalse(); - expect(field.validationSummary.message).toBe('D-M-YYYY hh:mm A'); + expect(widget.datetimeInputControl.invalid).toBeTrue(); + // expect(field.value).toBe('123abc'); + // expect(field.isValid).toBeFalse(); + // expect(field.validationSummary.message).toBe('D-M-YYYY hh:mm A'); }); it('should process direct keyboard input', async () => { @@ -181,9 +181,10 @@ describe('DateTimeWidgetComponent', () => { fixture.whenStable(); await fixture.whenStable(); - widget.onValueChanged({ target: { value: '9999-09-12T09:10:00.000Z' } } as any); + const input = await loader.getHarness(MatInputHarness); + await input.setValue('9999-09-12T09:10:00.000Z'); - expect(field.value).toBe('9999-09-12T09:10:00.000Z'); + expect(field.value).toEqual(new Date('9999-09-12T09:10:00.000Z')); expect(field.isValid).toBeTrue(); }); @@ -200,18 +201,11 @@ describe('DateTimeWidgetComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - widget.onValueChanged({ - target: { - value: '123abc' - } - } as any); - - fixture.detectChanges(); - await fixture.whenStable(); + const input = await loader.getHarness(MatInputHarness); + await input.setValue('123abc'); - expect(field.value).toBe('123abc'); - expect(field.isValid).toBeFalse(); - expect(field.validationSummary.message).toBe('D-M-YYYY hh:mm A'); + expect(widget.datetimeInputControl.invalid).toBeTrue(); + // expect(field.validationSummary.message).toBe('D-M-YYYY hh:mm A'); }); it('should allow empty dates when not required', async () => { @@ -227,10 +221,14 @@ describe('DateTimeWidgetComponent', () => { fixture.whenStable(); await fixture.whenStable(); - widget.onDateChanged({ value: null, targetElement: { value: '' } } as any); + // widget.onDateChanged({ value: null, targetElement: { value: '' } } as any); + const input = await loader.getHarness(MatInputHarness); + await input.setValue(''); - expect(field.value).toBe(''); - expect(field.isValid).toBeTrue(); + expect(widget.datetimeInputControl.value).toBe(null); + expect(widget.datetimeInputControl.valid).toBeTrue(); + // expect(field.value).toBe(''); + // expect(field.isValid).toBeTrue(); }); describe('when tooltip is set', () => { diff --git a/lib/core/src/lib/form/components/widgets/date-time/date-time.widget.ts b/lib/core/src/lib/form/components/widgets/date-time/date-time.widget.ts index a6cc9844c11..3d912f0ccae 100644 --- a/lib/core/src/lib/form/components/widgets/date-time/date-time.widget.ts +++ b/lib/core/src/lib/form/components/widgets/date-time/date-time.widget.ts @@ -18,19 +18,20 @@ /* eslint-disable @angular-eslint/component-selector */ import { NgIf } from '@angular/common'; -import { Component, Input, OnInit, ViewEncapsulation } from '@angular/core'; -import { FormsModule } from '@angular/forms'; +import { Component, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core'; +import { FormControl, ReactiveFormsModule, Validators } from '@angular/forms'; import { DateAdapter, MAT_DATE_FORMATS } from '@angular/material/core'; import { MatFormFieldModule } from '@angular/material/form-field'; import { MatInputModule } from '@angular/material/input'; import { MatTooltipModule } from '@angular/material/tooltip'; -import { DatetimeAdapter, MAT_DATETIME_FORMATS, MatDatetimepickerInputEvent, MatDatetimepickerModule } from '@mat-datetimepicker/core'; +import { DatetimeAdapter, MAT_DATETIME_FORMATS, MatDatetimepickerModule } from '@mat-datetimepicker/core'; import { TranslateModule } from '@ngx-translate/core'; import { isValid } from 'date-fns'; import { ADF_DATE_FORMATS, ADF_DATETIME_FORMATS, AdfDateFnsAdapter, AdfDateTimeFnsAdapter, DateFnsUtils } from '../../../../common'; import { FormService } from '../../../services/form.service'; import { ErrorWidgetComponent } from '../error/error.component'; import { WidgetComponent } from '../widget.component'; +import { Subscription } from 'rxjs'; @Component({ selector: 'date-time-widget', @@ -49,70 +50,71 @@ import { WidgetComponent } from '../widget.component'; MatFormFieldModule, MatInputModule, MatDatetimepickerModule, - FormsModule, + ReactiveFormsModule, MatTooltipModule, ErrorWidgetComponent ], encapsulation: ViewEncapsulation.None }) -export class DateTimeWidgetComponent extends WidgetComponent implements OnInit { +export class DateTimeWidgetComponent extends WidgetComponent implements OnInit, OnDestroy { minDate: Date; maxDate: Date; - @Input() - value: any = null; + datetimeInputControl: FormControl; + + private datetimeChangesSubscription: Subscription; constructor(public formService: FormService, private dateAdapter: DateAdapter, private dateTimeAdapter: DatetimeAdapter) { super(formService); } ngOnInit() { - if (this.field.dateDisplayFormat) { + this.initFormControl(); + this.initDateAdapter(); + this.initDateRange(); + this.subscribeToDateChanges(); + } + + private subscribeToDateChanges(): void { + this.datetimeChangesSubscription = this.datetimeInputControl.valueChanges.subscribe((newDate: Date) => { + if (newDate && isValid(newDate)) { + this.field.value = newDate; + this.onFieldChanged(this.field); + } + }); + } + + private initDateAdapter(): void { + if (this.field?.dateDisplayFormat) { const dateAdapter = this.dateAdapter as AdfDateFnsAdapter; dateAdapter.displayFormat = this.field.dateDisplayFormat; const dateTimeAdapter = this.dateTimeAdapter as AdfDateTimeFnsAdapter; dateTimeAdapter.displayFormat = this.field.dateDisplayFormat; } - - if (this.field) { - if (this.field.minValue) { - this.minDate = DateFnsUtils.localToUtc(new Date(this.field.minValue)); - } - - if (this.field.maxValue) { - this.maxDate = DateFnsUtils.localToUtc(new Date(this.field.maxValue)); - } - - if (this.field.value) { - this.value = DateFnsUtils.localToUtc(new Date(this.field.value)); - } - } } - onValueChanged(event: Event) { - const input = event.target as HTMLInputElement; - const newValue = this.dateTimeAdapter.parse(input.value, this.field.dateDisplayFormat); - - if (isValid(newValue)) { - this.field.value = DateFnsUtils.utcToLocal(newValue).toISOString(); - } else { - this.field.value = input.value; + private initDateRange(): void { + if (this.field?.minValue) { + this.minDate = DateFnsUtils.localToUtc(new Date(this.field.minValue)); } - this.onFieldChanged(this.field); + if (this.field?.maxValue) { + this.maxDate = DateFnsUtils.localToUtc(new Date(this.field.maxValue)); + } } - onDateChanged(event: MatDatetimepickerInputEvent) { - const newValue = event.value; - const input = event.targetElement as HTMLInputElement; - - if (newValue && isValid(newValue)) { - this.field.value = DateFnsUtils.utcToLocal(newValue).toISOString(); - } else { - this.field.value = input.value; - } + private initFormControl(): void { + this.datetimeInputControl = new FormControl( + { + value: this.field?.value, + disabled: this.field?.readOnly || this.readOnly + }, + this.isRequired() ? [Validators.required] : [] + ); + } - this.onFieldChanged(this.field); + ngOnDestroy(): void { + this.datetimeChangesSubscription?.unsubscribe(); } } diff --git a/lib/core/src/lib/form/components/widgets/date/date.widget.html b/lib/core/src/lib/form/components/widgets/date/date.widget.html index 5b05f452496..c68dc45110c 100644 --- a/lib/core/src/lib/form/components/widgets/date/date.widget.html +++ b/lib/core/src/lib/form/components/widgets/date/date.widget.html @@ -8,13 +8,10 @@ { widget.field = field; widget.ngOnInit(); - widget.onDateChange({ - value: new Date('1982/03/12') - } as any); + widget.dateInputControl.setValue(new Date('1982/03/12')); fixture.detectChanges(); await fixture.whenStable(); @@ -107,9 +105,7 @@ describe('DateWidgetComponent', () => { widget.field = field; widget.ngOnInit(); - widget.onDateChange({ - value: new Date('2023/03/13') - } as any); + widget.dateInputControl.setValue(new Date('2023/03/13')); fixture.detectChanges(); await fixture.whenStable(); @@ -142,7 +138,7 @@ describe('DateWidgetComponent', () => { expect(adapter.compareDate(widget.maxDate, expected)).toBe(0); }); - it('should eval visibility on date changed', () => { + it('should eval visibility on date changed', async () => { spyOn(widget, 'onFieldChanged').and.callThrough(); const field = new FormFieldModel(form, { @@ -153,9 +149,11 @@ describe('DateWidgetComponent', () => { }); widget.field = field; - widget.onDateChange({ - value: new Date('12/12/2012') - } as any); + + fixture.detectChanges(); + await fixture.whenStable(); + + widget.dateInputControl.setValue(new Date('12/12/2012')); expect(widget.onFieldChanged).toHaveBeenCalledWith(field); }); @@ -191,8 +189,8 @@ describe('DateWidgetComponent', () => { widget.field = new FormFieldModel(form, { id: 'date-field-id', name: 'date-name', - value: '9-9-9999', - type: 'date' + value: new Date('9-9-9999'), + type: FormFieldTypes.DATE }); fixture.detectChanges(); @@ -208,9 +206,9 @@ describe('DateWidgetComponent', () => { widget.field = new FormFieldModel(form, { id: 'date-field-id', name: 'date-name', - value: '30-12-9999', - type: 'date', - dateDisplayFormat: 'MM-DD-YYYY' + value: new Date('12-30-9999'), + type: FormFieldTypes.DATE, + dateDisplayFormat: 'MM-dd-yyyy' }); fixture.detectChanges(); @@ -219,8 +217,9 @@ describe('DateWidgetComponent', () => { let dateElement = element.querySelector('#date-field-id'); expect(dateElement?.value).toContain('12-30-9999'); - widget.field.value = '05-06-2019'; - widget.field.dateDisplayFormat = 'DD.MM.YYYY'; + dateElement.value = '05-06-2019'; + dateElement.dispatchEvent(new Event('input')); + widget.field.dateDisplayFormat = 'dd.MM.yyyy'; fixture.componentInstance.ngOnInit(); fixture.detectChanges(); @@ -272,9 +271,9 @@ describe('DateWidgetComponent', () => { const field = new FormFieldModel(form, { id: 'date-field-id', name: 'date-name', - value: '30-12-9999', - type: 'date', - dateDisplayFormat: 'MM-DD-YYYY' + value: new Date('12-30-9999'), + type: FormFieldTypes.DATE, + dateDisplayFormat: 'MM-dd-yyyy' }); widget.field = field; @@ -286,7 +285,8 @@ describe('DateWidgetComponent', () => { expect(dateElement).toBeDefined(); expect(dateElement.value).toContain('12-30-9999'); - widget.field.value = '03-02-2020'; + dateElement.value = '03-02-2020'; + dateElement.dispatchEvent(new Event('input')); fixture.componentInstance.ngOnInit(); fixture.detectChanges(); diff --git a/lib/core/src/lib/form/components/widgets/date/date.widget.ts b/lib/core/src/lib/form/components/widgets/date/date.widget.ts index b8342ccdff6..51549ee5e9c 100644 --- a/lib/core/src/lib/form/components/widgets/date/date.widget.ts +++ b/lib/core/src/lib/form/components/widgets/date/date.widget.ts @@ -18,18 +18,19 @@ /* eslint-disable @angular-eslint/component-selector */ import { NgIf } from '@angular/common'; -import { Component, Input, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core'; -import { FormsModule } from '@angular/forms'; +import { Component, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core'; +import { FormControl, ReactiveFormsModule, Validators } from '@angular/forms'; import { DateAdapter, MAT_DATE_FORMATS } from '@angular/material/core'; import { MatDatepickerInputEvent, MatDatepickerModule } from '@angular/material/datepicker'; import { MatFormFieldModule } from '@angular/material/form-field'; import { MatInputModule } from '@angular/material/input'; import { TranslateModule } from '@ngx-translate/core'; -import { Subject } from 'rxjs'; +import { Subscription } from 'rxjs'; import { ADF_DATE_FORMATS, AdfDateFnsAdapter } from '../../../../common'; import { FormService } from '../../../services/form.service'; import { ErrorWidgetComponent } from '../error/error.component'; import { WidgetComponent } from '../widget.component'; +import { isValid } from 'date-fns'; @Component({ selector: 'date-widget', @@ -50,7 +51,7 @@ import { WidgetComponent } from '../widget.component'; '(invalid)': 'event($event)', '(select)': 'event($event)' }, - imports: [MatFormFieldModule, TranslateModule, MatInputModule, MatDatepickerModule, FormsModule, ErrorWidgetComponent, NgIf], + imports: [MatFormFieldModule, TranslateModule, MatInputModule, MatDatepickerModule, ReactiveFormsModule, ErrorWidgetComponent, NgIf], encapsulation: ViewEncapsulation.None }) export class DateWidgetComponent extends WidgetComponent implements OnInit, OnDestroy { @@ -60,52 +61,75 @@ export class DateWidgetComponent extends WidgetComponent implements OnInit, OnDe maxDate: Date; startAt: Date; - @Input() - value: any = null; + dateInputControl: FormControl; - private onDestroy$ = new Subject(); + private dateChangesSubscription: Subscription; constructor(public formService: FormService, private dateAdapter: DateAdapter) { super(formService); } ngOnInit() { - if (this.field.dateDisplayFormat) { + this.initFormControl(); + this.initDateAdapter(); + this.initDateRange(); + this.initStartAt(); + this.subscribeToDateChanges(); + } + + private subscribeToDateChanges(): void { + this.dateChangesSubscription = this.dateInputControl.valueChanges.subscribe((newDate: Date) => { + if (newDate && isValid(newDate)) { + this.field.value = newDate; + this.onFieldChanged(this.field); + } + }); + } + + private initFormControl(): void { + this.dateInputControl = new FormControl( + { + value: this.field?.value, + disabled: this.field?.readOnly || this.readOnly + }, + this.isRequired() ? [Validators.required] : [] + ); + } + + private initDateAdapter(): void { + if (this.field?.dateDisplayFormat) { const adapter = this.dateAdapter as AdfDateFnsAdapter; adapter.displayFormat = this.field.dateDisplayFormat; } + } - if (this.field) { - if (this.field.minValue) { - this.minDate = this.dateAdapter.parse(this.field.minValue, this.DATE_FORMAT); - } - - if (this.field.maxValue) { - this.maxDate = this.dateAdapter.parse(this.field.maxValue, this.DATE_FORMAT); - } + private initDateRange(): void { + if (this.field?.minValue) { + this.minDate = this.dateAdapter.parse(this.field.minValue, this.DATE_FORMAT); + } - if (this.field.value) { - this.startAt = this.dateAdapter.parse(this.field.value, this.DATE_FORMAT); - this.value = this.dateAdapter.parse(this.field.value, this.DATE_FORMAT); - } + if (this.field?.maxValue) { + this.maxDate = this.dateAdapter.parse(this.field.maxValue, this.DATE_FORMAT); } } - ngOnDestroy() { - this.onDestroy$.next(true); - this.onDestroy$.complete(); + private initStartAt(): void { + if (this.field?.value) { + this.startAt = this.dateAdapter.parse(this.field.value, this.DATE_FORMAT); + } } - onDateChange(event: MatDatepickerInputEvent) { + onDateChanged(event: MatDatepickerInputEvent): void { const value = event.value; - const input = event.targetElement as HTMLInputElement; - if (value) { - this.field.value = this.dateAdapter.format(value, this.DATE_FORMAT); - } else { - this.field.value = input.value; + this.field.value = value; + this.dateInputControl.setValue(value); } this.onFieldChanged(this.field); } + + ngOnDestroy(): void { + this.dateChangesSubscription?.unsubscribe(); + } } diff --git a/lib/process-services-cloud/src/lib/form/components/widgets/date/date-cloud.widget.html b/lib/process-services-cloud/src/lib/form/components/widgets/date/date-cloud.widget.html index a36a586a4b5..36759bbdb2a 100644 --- a/lib/process-services-cloud/src/lib/form/components/widgets/date/date-cloud.widget.html +++ b/lib/process-services-cloud/src/lib/form/components/widgets/date/date-cloud.widget.html @@ -7,18 +7,16 @@ - { expect(isEqual(widget.maxDate, expected)).toBeTrue(); }); - it('should eval visibility on date changed', () => { + it('should eval visibility on date changed', async () => { spyOn(widget, 'onFieldChanged').and.callThrough(); const field = new FormFieldModel(form, { @@ -101,7 +101,11 @@ describe('DateWidgetComponent', () => { }); widget.field = field; - widget.onDateChanged({ value: adapter.today() } as any); + + fixture.detectChanges(); + await fixture.whenStable(); + + widget.dateInputControl.setValue(new Date('9999-9-9')); expect(widget.onFieldChanged).toHaveBeenCalledWith(field); }); @@ -116,7 +120,6 @@ describe('DateWidgetComponent', () => { widget.field = new FormFieldModel(form, { id: 'date-field-id', name: 'date-name', - // always stored as dd-MM-yyyy value: '9999-9-9', type: FormFieldTypes.DATE }); @@ -134,10 +137,9 @@ describe('DateWidgetComponent', () => { widget.field = new FormFieldModel(form, { id: 'date-field-id', name: 'date-name', - // always stored as dd-MM-yyyy - value: '30-12-9999', + value: new Date('12-30-9999'), type: FormFieldTypes.DATE, - dateDisplayFormat: 'YYYY-DD-MM' + dateDisplayFormat: 'yyyy-dd-MM' }); fixture.detectChanges(); @@ -153,7 +155,7 @@ describe('DateWidgetComponent', () => { name: 'date-name', value: '9999-9-9', type: FormFieldTypes.DATE, - readOnly: 'false' + readOnly: false }); widget.field.isVisible = true; widget.field.readOnly = false; @@ -193,11 +195,10 @@ describe('DateWidgetComponent', () => { const field = new FormFieldModel(form, { id: 'date-field-id', name: 'date-name', - // always stored as dd-MM-yyyy - value: '30-12-9999', + value: new Date('12-30-9999'), type: FormFieldTypes.DATE, - readOnly: 'false', - dateDisplayFormat: 'MM-DD-YYYY' + readOnly: false, + dateDisplayFormat: 'MM-dd-yyyy' }); widget.field = field; @@ -208,7 +209,8 @@ describe('DateWidgetComponent', () => { expect(dateElement).toBeDefined(); expect(dateElement.value).toContain('12-30-9999'); - widget.field.value = '03-02-2020'; + dateElement.value = '03-02-2020'; + dateElement.dispatchEvent(new Event('input')); fixture.componentInstance.ngOnInit(); fixture.detectChanges(); diff --git a/lib/process-services-cloud/src/lib/form/components/widgets/date/date-cloud.widget.ts b/lib/process-services-cloud/src/lib/form/components/widgets/date/date-cloud.widget.ts index 0f0aceb4a64..9ac17cc657c 100644 --- a/lib/process-services-cloud/src/lib/form/components/widgets/date/date-cloud.widget.ts +++ b/lib/process-services-cloud/src/lib/form/components/widgets/date/date-cloud.widget.ts @@ -17,15 +17,32 @@ /* eslint-disable @angular-eslint/component-selector */ -import { Component, OnInit, ViewEncapsulation, OnDestroy, Input } from '@angular/core'; +import { Component, OnInit, ViewEncapsulation, OnDestroy } from '@angular/core'; import { DateAdapter, MAT_DATE_FORMATS } from '@angular/material/core'; -import { Subject } from 'rxjs'; -import { WidgetComponent, FormService, AdfDateFnsAdapter, DateFnsUtils, ADF_DATE_FORMATS } from '@alfresco/adf-core'; -import { MatDatepickerInputEvent } from '@angular/material/datepicker'; -import { addDays } from 'date-fns'; +import { Subscription } from 'rxjs'; +import { WidgetComponent, FormService, AdfDateFnsAdapter, DateFnsUtils, ADF_DATE_FORMATS, ErrorWidgetComponent } from '@alfresco/adf-core'; +import { MatDatepickerModule } from '@angular/material/datepicker'; +import { addDays, isValid } from 'date-fns'; +import { FormControl, ReactiveFormsModule, Validators } from '@angular/forms'; +import { CommonModule } from '@angular/common'; +import { TranslateModule } from '@ngx-translate/core'; +import { MatFormFieldModule } from '@angular/material/form-field'; +import { MatInputModule } from '@angular/material/input'; +import { MatTooltipModule } from '@angular/material/tooltip'; @Component({ selector: 'date-widget', + standalone: true, + imports: [ + CommonModule, + TranslateModule, + MatFormFieldModule, + MatInputModule, + MatTooltipModule, + MatDatepickerModule, + ReactiveFormsModule, + ErrorWidgetComponent + ], providers: [ { provide: MAT_DATE_FORMATS, useValue: ADF_DATE_FORMATS }, { provide: DateAdapter, useClass: AdfDateFnsAdapter } @@ -46,81 +63,88 @@ import { addDays } from 'date-fns'; encapsulation: ViewEncapsulation.None }) export class DateCloudWidgetComponent extends WidgetComponent implements OnInit, OnDestroy { - typeId = 'DateCloudWidgetComponent'; readonly DATE_FORMAT = 'dd-MM-yyyy'; minDate: Date = null; maxDate: Date = null; startAt: Date = null; - /** - * Current date value. - * The value is always stored in the format `dd-MM-yyyy`, - * but displayed in the UI component using `dateDisplayFormat` - */ - @Input() - value: any = null; + dateInputControl: FormControl; - private onDestroy$ = new Subject(); + private dateChangesSubscription: Subscription; - constructor(public formService: FormService, private dateAdapter: DateAdapter) { + constructor(public readonly formService: FormService, private readonly dateAdapter: DateAdapter) { super(formService); } ngOnInit() { - if (this.field.dateDisplayFormat) { - const adapter = this.dateAdapter as AdfDateFnsAdapter; - adapter.displayFormat = this.field.dateDisplayFormat; - } - - if (this.field) { - if (this.field.dynamicDateRangeSelection) { - if (this.field.minDateRangeValue === null) { - this.minDate = null; - this.field.minValue = null; - } else { - this.minDate = addDays(this.dateAdapter.today(), this.field.minDateRangeValue); - this.field.minValue = DateFnsUtils.formatDate(this.minDate, this.DATE_FORMAT); - } - if (this.field.maxDateRangeValue === null) { - this.maxDate = null; - this.field.maxValue = null; - } else { - this.maxDate = addDays(this.dateAdapter.today(), this.field.maxDateRangeValue); - this.field.maxValue = DateFnsUtils.formatDate(this.maxDate, this.DATE_FORMAT); - } - } else { - if (this.field.minValue) { - this.minDate = this.dateAdapter.parse(this.field.minValue, this.DATE_FORMAT); - } + this.initFormControl(); + this.initDateAdapter(); + this.initRangeSelection(); + this.initStartAt(); + this.subscribeToDateChanges(); + } - if (this.field.maxValue) { - this.maxDate = this.dateAdapter.parse(this.field.maxValue, this.DATE_FORMAT); - } + private subscribeToDateChanges(): void { + this.dateChangesSubscription = this.dateInputControl.valueChanges.subscribe((newDate: Date) => { + if (newDate && isValid(newDate)) { + this.field.value = newDate; + this.onFieldChanged(this.field); } + }); + } - if (this.field.value) { - this.startAt = this.dateAdapter.parse(this.field.value, this.DATE_FORMAT); - this.value = this.dateAdapter.parse(this.field.value, this.DATE_FORMAT); - } - } + private initFormControl(): void { + this.dateInputControl = new FormControl( + { + value: this.field?.value, + disabled: this.field?.readOnly || this.readOnly + }, + this.isRequired() ? [Validators.required] : [] + ); } - ngOnDestroy() { - this.onDestroy$.next(true); - this.onDestroy$.complete(); + private initDateAdapter(): void { + if (this.field?.dateDisplayFormat) { + const adapter = this.dateAdapter as AdfDateFnsAdapter; + adapter.displayFormat = this.field.dateDisplayFormat; + } } - onDateChanged(event: MatDatepickerInputEvent) { - const value = event.value; - const input = event.targetElement as HTMLInputElement; + private initStartAt(): void { + if (this.field?.value) { + this.startAt = this.dateAdapter.parse(this.field.value, this.DATE_FORMAT); + } + } - if (value) { - this.field.value = this.dateAdapter.format(value, this.DATE_FORMAT); + private initRangeSelection(): void { + if (this.field?.dynamicDateRangeSelection) { + if (this.field.minDateRangeValue === null) { + this.minDate = null; + this.field.minValue = null; + } else { + this.minDate = addDays(this.dateAdapter.today(), this.field.minDateRangeValue); + this.field.minValue = DateFnsUtils.formatDate(this.minDate, this.DATE_FORMAT); + } + if (this.field.maxDateRangeValue === null) { + this.maxDate = null; + this.field.maxValue = null; + } else { + this.maxDate = addDays(this.dateAdapter.today(), this.field.maxDateRangeValue); + this.field.maxValue = DateFnsUtils.formatDate(this.maxDate, this.DATE_FORMAT); + } } else { - this.field.value = input.value; + if (this.field?.minValue) { + this.minDate = this.dateAdapter.parse(this.field.minValue, this.DATE_FORMAT); + } + + if (this.field?.maxValue) { + this.maxDate = this.dateAdapter.parse(this.field.maxValue, this.DATE_FORMAT); + } } + } - this.onFieldChanged(this.field); + ngOnDestroy(): void { + this.dateChangesSubscription?.unsubscribe(); } } diff --git a/lib/process-services-cloud/src/lib/form/form-cloud.module.ts b/lib/process-services-cloud/src/lib/form/form-cloud.module.ts index a20f4567f20..9255a2d4b7e 100644 --- a/lib/process-services-cloud/src/lib/form/form-cloud.module.ts +++ b/lib/process-services-cloud/src/lib/form/form-cloud.module.ts @@ -24,8 +24,6 @@ import { FormCloudComponent } from './components/form-cloud.component'; import { FormDefinitionSelectorCloudComponent } from './components/form-definition-selector-cloud.component'; import { FormCustomOutcomesComponent } from './components/form-cloud-custom-outcomes.component'; import { AlfrescoViewerModule, ContentMetadataModule, ContentNodeSelectorModule, UploadModule } from '@alfresco/adf-content-services'; - -import { DateCloudWidgetComponent } from './components/widgets/date/date-cloud.widget'; import { DropdownCloudWidgetComponent } from './components/widgets/dropdown/dropdown-cloud.widget'; import { GroupCloudWidgetComponent } from './components/widgets/group/group-cloud.widget'; import { PeopleCloudWidgetComponent } from './components/widgets/people/people-cloud.widget'; @@ -73,7 +71,6 @@ import { FormCloudSpinnerService } from './services/spinner/form-cloud-spinner.s DropdownCloudWidgetComponent, RadioButtonsCloudWidgetComponent, AttachFileCloudWidgetComponent, - DateCloudWidgetComponent, PeopleCloudWidgetComponent, GroupCloudWidgetComponent, PropertiesViewerWrapperComponent, @@ -91,7 +88,6 @@ import { FormCloudSpinnerService } from './services/spinner/form-cloud-spinner.s DropdownCloudWidgetComponent, RadioButtonsCloudWidgetComponent, AttachFileCloudWidgetComponent, - DateCloudWidgetComponent, PeopleCloudWidgetComponent, GroupCloudWidgetComponent, PropertiesViewerWidgetComponent,