mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-07-24 17:32:15 +00:00
AAE-27343 Listen to form rules changes from reactive widgets (#10392)
* AAE-27343 Listen to form rules changes from reactive widgets * remove leftover * apply interface for reactive widgets and unit test * update readonly control status * [ci:force][link-adf:fix/AAE-27343-listen-to-form-rules-changes-in-reactive-widgets]
This commit is contained in:
@@ -42,7 +42,7 @@ describe('FormFieldComponent', () => {
|
|||||||
fixture.destroy();
|
fixture.destroy();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should create default component instance', (done) => {
|
it('should create default component instance', () => {
|
||||||
const field = new FormFieldModel(form, {
|
const field = new FormFieldModel(form, {
|
||||||
type: FormFieldTypes.TEXT,
|
type: FormFieldTypes.TEXT,
|
||||||
id: 'FAKE-TXT-WIDGET'
|
id: 'FAKE-TXT-WIDGET'
|
||||||
@@ -51,14 +51,29 @@ describe('FormFieldComponent', () => {
|
|||||||
component.field = field;
|
component.field = field;
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
fixture.whenStable().then(() => {
|
expect(component.componentRef).toBeDefined();
|
||||||
expect(component.componentRef).toBeDefined();
|
expect(component.componentRef.instance instanceof TextWidgetComponent).toBeTruthy();
|
||||||
expect(component.componentRef.instance instanceof TextWidgetComponent).toBeTruthy();
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should create custom component instance', (done) => {
|
it('should call update form control state for reactive type widget on formRulesEvent change', () => {
|
||||||
|
const field = new FormFieldModel(form, {
|
||||||
|
type: FormFieldTypes.DATE,
|
||||||
|
id: 'FAKE-DATE-WIDGET'
|
||||||
|
});
|
||||||
|
|
||||||
|
component.field = field;
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
const widgetInstance = component.componentRef.instance;
|
||||||
|
const updateFormControlState = spyOn(widgetInstance, 'updateReactiveFormControl');
|
||||||
|
|
||||||
|
widgetInstance.formService.formRulesEvent.next();
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
expect(updateFormControlState).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create custom component instance', () => {
|
||||||
formRenderingService.setComponentTypeResolver(FormFieldTypes.AMOUNT, () => CheckboxWidgetComponent, true);
|
formRenderingService.setComponentTypeResolver(FormFieldTypes.AMOUNT, () => CheckboxWidgetComponent, true);
|
||||||
|
|
||||||
const field = new FormFieldModel(form, {
|
const field = new FormFieldModel(form, {
|
||||||
@@ -67,16 +82,14 @@ describe('FormFieldComponent', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
component.field = field;
|
component.field = field;
|
||||||
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
fixture.whenStable().then(() => {
|
expect(component.componentRef).toBeDefined();
|
||||||
expect(component.componentRef).toBeDefined();
|
expect(component.componentRef.instance instanceof CheckboxWidgetComponent).toBeTruthy();
|
||||||
expect(component.componentRef.instance instanceof CheckboxWidgetComponent).toBeTruthy();
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should require component type to be resolved', (done) => {
|
it('should require component type to be resolved', () => {
|
||||||
const field = new FormFieldModel(form, {
|
const field = new FormFieldModel(form, {
|
||||||
type: FormFieldTypes.TEXT,
|
type: FormFieldTypes.TEXT,
|
||||||
id: 'FAKE-TXT-WIDGET'
|
id: 'FAKE-TXT-WIDGET'
|
||||||
@@ -84,16 +97,14 @@ describe('FormFieldComponent', () => {
|
|||||||
|
|
||||||
spyOn(formRenderingService, 'resolveComponentType').and.returnValue(null);
|
spyOn(formRenderingService, 'resolveComponentType').and.returnValue(null);
|
||||||
component.field = field;
|
component.field = field;
|
||||||
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
fixture.whenStable().then(() => {
|
expect(formRenderingService.resolveComponentType).toHaveBeenCalled();
|
||||||
expect(formRenderingService.resolveComponentType).toHaveBeenCalled();
|
expect(component.componentRef).toBeUndefined();
|
||||||
expect(component.componentRef).toBeUndefined();
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should hide the field when it is not visible', (done) => {
|
it('should hide the field when it is not visible', () => {
|
||||||
const field = new FormFieldModel(form, {
|
const field = new FormFieldModel(form, {
|
||||||
type: FormFieldTypes.TEXT,
|
type: FormFieldTypes.TEXT,
|
||||||
id: 'FAKE-TXT-WIDGET'
|
id: 'FAKE-TXT-WIDGET'
|
||||||
@@ -101,29 +112,26 @@ describe('FormFieldComponent', () => {
|
|||||||
|
|
||||||
component.field = field;
|
component.field = field;
|
||||||
component.field.isVisible = false;
|
component.field.isVisible = false;
|
||||||
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
fixture.whenStable().then(() => {
|
|
||||||
const debugElement = fixture.nativeElement.querySelector('#field-FAKE-TXT-WIDGET-container').style;
|
const debugElement = fixture.nativeElement.querySelector('#field-FAKE-TXT-WIDGET-container').style;
|
||||||
expect(debugElement.visibility).toEqual('hidden');
|
expect(debugElement.visibility).toEqual('hidden');
|
||||||
expect(debugElement.display).toEqual('none');
|
expect(debugElement.display).toEqual('none');
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should show the field when it is visible', (done) => {
|
it('should show the field when it is visible', () => {
|
||||||
const field = new FormFieldModel(form, {
|
const field = new FormFieldModel(form, {
|
||||||
type: FormFieldTypes.TEXT,
|
type: FormFieldTypes.TEXT,
|
||||||
id: 'FAKE-TXT-WIDGET'
|
id: 'FAKE-TXT-WIDGET'
|
||||||
});
|
});
|
||||||
|
|
||||||
component.field = field;
|
component.field = field;
|
||||||
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
fixture.whenStable().then(() => {
|
expect(fixture.nativeElement.querySelector('#field-FAKE-TXT-WIDGET-container').style.visibility).toEqual('visible');
|
||||||
expect(fixture.nativeElement.querySelector('#field-FAKE-TXT-WIDGET-container').style.visibility).toEqual('visible');
|
expect(fixture.nativeElement.querySelector('#field-FAKE-TXT-WIDGET-container').style.display).toEqual('block');
|
||||||
expect(fixture.nativeElement.querySelector('#field-FAKE-TXT-WIDGET-container').style.display).toEqual('block');
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should hide a visible element', () => {
|
it('should hide a visible element', () => {
|
||||||
@@ -142,7 +150,7 @@ describe('FormFieldComponent', () => {
|
|||||||
expect(fixture.nativeElement.querySelector('#field-FAKE-TXT-WIDGET-container').style.display).toEqual('none');
|
expect(fixture.nativeElement.querySelector('#field-FAKE-TXT-WIDGET-container').style.display).toEqual('none');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('[C213878] - Should fields be correctly rendered when filled with process variables', async () => {
|
it('[C213878] - Should fields be correctly rendered when filled with process variables', () => {
|
||||||
const field = new FormFieldModel(form, {
|
const field = new FormFieldModel(form, {
|
||||||
fieldType: 'HyperlinkRepresentation',
|
fieldType: 'HyperlinkRepresentation',
|
||||||
id: 'label2',
|
id: 'label2',
|
||||||
|
@@ -20,6 +20,7 @@ import {
|
|||||||
Component,
|
Component,
|
||||||
ComponentFactory,
|
ComponentFactory,
|
||||||
ComponentRef,
|
ComponentRef,
|
||||||
|
DestroyRef,
|
||||||
inject,
|
inject,
|
||||||
Input,
|
Input,
|
||||||
NgModule,
|
NgModule,
|
||||||
@@ -33,6 +34,8 @@ import { FormRenderingService } from '../../services/form-rendering.service';
|
|||||||
import { WidgetVisibilityService } from '../../services/widget-visibility.service';
|
import { WidgetVisibilityService } from '../../services/widget-visibility.service';
|
||||||
import { FormFieldModel } from '../widgets/core/form-field.model';
|
import { FormFieldModel } from '../widgets/core/form-field.model';
|
||||||
import { FieldStylePipe } from '../../pipes/field-style.pipe';
|
import { FieldStylePipe } from '../../pipes/field-style.pipe';
|
||||||
|
import { FormFieldTypes } from '../widgets/core/form-field-types';
|
||||||
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
||||||
|
|
||||||
declare const adf: any;
|
declare const adf: any;
|
||||||
|
|
||||||
@@ -62,6 +65,7 @@ export class FormFieldComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
private readonly formRenderingService = inject(FormRenderingService);
|
private readonly formRenderingService = inject(FormRenderingService);
|
||||||
private readonly visibilityService = inject(WidgetVisibilityService);
|
private readonly visibilityService = inject(WidgetVisibilityService);
|
||||||
|
private readonly destroyRef = inject(DestroyRef);
|
||||||
private readonly compiler = inject(Compiler);
|
private readonly compiler = inject(Compiler);
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
@@ -88,14 +92,29 @@ export class FormFieldComponent implements OnInit, OnDestroy {
|
|||||||
instance.fieldChanged.subscribe((field) => {
|
instance.fieldChanged.subscribe((field) => {
|
||||||
if (field && this.field.form) {
|
if (field && this.field.form) {
|
||||||
this.visibilityService.refreshVisibility(field.form);
|
this.visibilityService.refreshVisibility(field.form);
|
||||||
field.form.onFormFieldChanged(field);
|
this.triggerFormFieldChanged(field);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (FormFieldTypes.isReactiveType(instance?.field?.type)) {
|
||||||
|
this.updateReactiveFormControlOnFormRulesEvent(instance);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private updateReactiveFormControlOnFormRulesEvent(instance: any): void {
|
||||||
|
instance?.formService.formRulesEvent.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(() => {
|
||||||
|
instance?.updateReactiveFormControl();
|
||||||
|
this.triggerFormFieldChanged(instance.field);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private triggerFormFieldChanged(field: FormFieldModel): void {
|
||||||
|
field.form.onFormFieldChanged(field);
|
||||||
|
}
|
||||||
|
|
||||||
ngOnDestroy() {
|
ngOnDestroy() {
|
||||||
if (this.componentRef) {
|
if (this.componentRef) {
|
||||||
this.componentRef.destroy();
|
this.componentRef.destroy();
|
||||||
|
@@ -57,15 +57,14 @@ export class DateTimeWidgetComponent extends WidgetComponent implements OnInit {
|
|||||||
maxDate: Date;
|
maxDate: Date;
|
||||||
datetimeInputControl: FormControl<Date> = new FormControl<Date>(null);
|
datetimeInputControl: FormControl<Date> = new FormControl<Date>(null);
|
||||||
|
|
||||||
|
|
||||||
public readonly formService = inject(FormService);
|
public readonly formService = inject(FormService);
|
||||||
|
|
||||||
private readonly destroyRef = inject(DestroyRef);
|
private readonly destroyRef = inject(DestroyRef);
|
||||||
private readonly dateAdapter = inject(DateAdapter);
|
private readonly dateAdapter = inject(DateAdapter);
|
||||||
private readonly dateTimeAdapter = inject(DatetimeAdapter);
|
private readonly dateTimeAdapter = inject(DatetimeAdapter);
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.patchFormControl();
|
this.setFormControlValue();
|
||||||
|
this.updateFormControlState();
|
||||||
this.initDateAdapter();
|
this.initDateAdapter();
|
||||||
this.initDateRange();
|
this.initDateRange();
|
||||||
this.subscribeToDateChanges();
|
this.subscribeToDateChanges();
|
||||||
@@ -77,12 +76,20 @@ export class DateTimeWidgetComponent extends WidgetComponent implements OnInit {
|
|||||||
this.onFieldChanged(this.field);
|
this.onFieldChanged(this.field);
|
||||||
}
|
}
|
||||||
|
|
||||||
private patchFormControl(): void {
|
updateReactiveFormControl(): void {
|
||||||
|
this.updateFormControlState();
|
||||||
|
this.validateField();
|
||||||
|
}
|
||||||
|
|
||||||
|
private setFormControlValue(): void {
|
||||||
this.datetimeInputControl.setValue(this.field.value, { emitEvent: false });
|
this.datetimeInputControl.setValue(this.field.value, { emitEvent: false });
|
||||||
|
}
|
||||||
|
|
||||||
|
private updateFormControlState(): void {
|
||||||
this.datetimeInputControl.setValidators(this.isRequired() ? [Validators.required] : []);
|
this.datetimeInputControl.setValidators(this.isRequired() ? [Validators.required] : []);
|
||||||
if (this.field?.readOnly || this.readOnly) {
|
this.field?.readOnly || this.readOnly
|
||||||
this.datetimeInputControl.disable({ emitEvent: false });
|
? this.datetimeInputControl.disable({ emitEvent: false })
|
||||||
}
|
: this.datetimeInputControl.enable({ emitEvent: false });
|
||||||
|
|
||||||
this.datetimeInputControl.updateValueAndValidity({ emitEvent: false });
|
this.datetimeInputControl.updateValueAndValidity({ emitEvent: false });
|
||||||
}
|
}
|
||||||
|
@@ -32,6 +32,7 @@ import { WidgetComponent } from '../widget.component';
|
|||||||
import { ErrorMessageModel } from '../core/error-message.model';
|
import { ErrorMessageModel } from '../core/error-message.model';
|
||||||
import { parseISO } from 'date-fns';
|
import { parseISO } from 'date-fns';
|
||||||
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
||||||
|
import { ReactiveFormWidget } from '../reactive-widget.interface';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'date-widget',
|
selector: 'date-widget',
|
||||||
@@ -55,7 +56,7 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|||||||
imports: [MatFormFieldModule, TranslateModule, MatInputModule, MatDatepickerModule, ReactiveFormsModule, ErrorWidgetComponent, NgIf],
|
imports: [MatFormFieldModule, TranslateModule, MatInputModule, MatDatepickerModule, ReactiveFormsModule, ErrorWidgetComponent, NgIf],
|
||||||
encapsulation: ViewEncapsulation.None
|
encapsulation: ViewEncapsulation.None
|
||||||
})
|
})
|
||||||
export class DateWidgetComponent extends WidgetComponent implements OnInit {
|
export class DateWidgetComponent extends WidgetComponent implements OnInit, ReactiveFormWidget {
|
||||||
minDate: Date;
|
minDate: Date;
|
||||||
maxDate: Date;
|
maxDate: Date;
|
||||||
startAt: Date;
|
startAt: Date;
|
||||||
@@ -68,7 +69,8 @@ export class DateWidgetComponent extends WidgetComponent implements OnInit {
|
|||||||
private readonly destroyRef = inject(DestroyRef);
|
private readonly destroyRef = inject(DestroyRef);
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.patchFormControl();
|
this.setFormControlValue();
|
||||||
|
this.updateFormControlState();
|
||||||
this.initDateAdapter();
|
this.initDateAdapter();
|
||||||
this.initDateRange();
|
this.initDateRange();
|
||||||
this.initStartAt();
|
this.initStartAt();
|
||||||
@@ -80,12 +82,21 @@ export class DateWidgetComponent extends WidgetComponent implements OnInit {
|
|||||||
this.validateField();
|
this.validateField();
|
||||||
this.onFieldChanged(this.field);
|
this.onFieldChanged(this.field);
|
||||||
}
|
}
|
||||||
private patchFormControl(): void {
|
|
||||||
|
updateReactiveFormControl(): void {
|
||||||
|
this.updateFormControlState();
|
||||||
|
this.validateField();
|
||||||
|
}
|
||||||
|
|
||||||
|
private setFormControlValue(): void {
|
||||||
this.dateInputControl.setValue(this.field.value, { emitEvent: false });
|
this.dateInputControl.setValue(this.field.value, { emitEvent: false });
|
||||||
|
}
|
||||||
|
|
||||||
|
private updateFormControlState(): void {
|
||||||
this.dateInputControl.setValidators(this.isRequired() ? [Validators.required] : []);
|
this.dateInputControl.setValidators(this.isRequired() ? [Validators.required] : []);
|
||||||
if (this.field?.readOnly || this.readOnly) {
|
this.field?.readOnly || this.readOnly
|
||||||
this.dateInputControl.disable({ emitEvent: false });
|
? this.dateInputControl.disable({ emitEvent: false })
|
||||||
}
|
: this.dateInputControl.enable({ emitEvent: false });
|
||||||
|
|
||||||
this.dateInputControl.updateValueAndValidity({ emitEvent: false });
|
this.dateInputControl.updateValueAndValidity({ emitEvent: false });
|
||||||
}
|
}
|
||||||
|
@@ -34,6 +34,7 @@ import { DecimalWidgetComponent } from './decimal/decimal.component';
|
|||||||
|
|
||||||
// core
|
// core
|
||||||
export * from './widget.component';
|
export * from './widget.component';
|
||||||
|
export * from './reactive-widget.interface';
|
||||||
export * from './core';
|
export * from './core';
|
||||||
|
|
||||||
// primitives
|
// primitives
|
||||||
|
@@ -0,0 +1,23 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { FormService } from '../../services/form.service';
|
||||||
|
|
||||||
|
export interface ReactiveFormWidget {
|
||||||
|
updateReactiveFormControl(): void;
|
||||||
|
formService: FormService;
|
||||||
|
}
|
@@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
/* eslint-disable @angular-eslint/component-selector */
|
/* eslint-disable @angular-eslint/component-selector */
|
||||||
|
|
||||||
import { Component, DestroyRef, inject, OnInit, ViewEncapsulation } from '@angular/core';
|
import { Component, OnInit, ViewEncapsulation, DestroyRef, inject } from '@angular/core';
|
||||||
import { DateAdapter, MAT_DATE_FORMATS } from '@angular/material/core';
|
import { DateAdapter, MAT_DATE_FORMATS } from '@angular/material/core';
|
||||||
import {
|
import {
|
||||||
ADF_DATE_FORMATS,
|
ADF_DATE_FORMATS,
|
||||||
@@ -27,7 +27,8 @@ import {
|
|||||||
ErrorMessageModel,
|
ErrorMessageModel,
|
||||||
ErrorWidgetComponent,
|
ErrorWidgetComponent,
|
||||||
FormService,
|
FormService,
|
||||||
WidgetComponent
|
WidgetComponent,
|
||||||
|
ReactiveFormWidget
|
||||||
} from '@alfresco/adf-core';
|
} from '@alfresco/adf-core';
|
||||||
import { MatDatepickerModule } from '@angular/material/datepicker';
|
import { MatDatepickerModule } from '@angular/material/datepicker';
|
||||||
import { addDays, parseISO } from 'date-fns';
|
import { addDays, parseISO } from 'date-fns';
|
||||||
@@ -61,7 +62,7 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|||||||
},
|
},
|
||||||
encapsulation: ViewEncapsulation.None
|
encapsulation: ViewEncapsulation.None
|
||||||
})
|
})
|
||||||
export class DateCloudWidgetComponent extends WidgetComponent implements OnInit {
|
export class DateCloudWidgetComponent extends WidgetComponent implements OnInit, ReactiveFormWidget {
|
||||||
typeId = 'DateCloudWidgetComponent';
|
typeId = 'DateCloudWidgetComponent';
|
||||||
|
|
||||||
minDate: Date = null;
|
minDate: Date = null;
|
||||||
@@ -76,7 +77,8 @@ export class DateCloudWidgetComponent extends WidgetComponent implements OnInit
|
|||||||
private readonly dateAdapter = inject(DateAdapter);
|
private readonly dateAdapter = inject(DateAdapter);
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.patchFormControl();
|
this.setFormControlValue();
|
||||||
|
this.updateFormControlState();
|
||||||
this.initDateAdapter();
|
this.initDateAdapter();
|
||||||
this.initRangeSelection();
|
this.initRangeSelection();
|
||||||
this.initStartAt();
|
this.initStartAt();
|
||||||
@@ -89,12 +91,20 @@ export class DateCloudWidgetComponent extends WidgetComponent implements OnInit
|
|||||||
this.onFieldChanged(this.field);
|
this.onFieldChanged(this.field);
|
||||||
}
|
}
|
||||||
|
|
||||||
private patchFormControl(): void {
|
updateReactiveFormControl(): void {
|
||||||
|
this.updateFormControlState();
|
||||||
|
this.validateField();
|
||||||
|
}
|
||||||
|
|
||||||
|
private setFormControlValue(): void {
|
||||||
this.dateInputControl.setValue(this.field.value, { emitEvent: false });
|
this.dateInputControl.setValue(this.field.value, { emitEvent: false });
|
||||||
|
}
|
||||||
|
|
||||||
|
private updateFormControlState(): void {
|
||||||
this.dateInputControl.setValidators(this.isRequired() ? [Validators.required] : []);
|
this.dateInputControl.setValidators(this.isRequired() ? [Validators.required] : []);
|
||||||
if (this.field?.readOnly || this.readOnly) {
|
this.field?.readOnly || this.readOnly
|
||||||
this.dateInputControl.disable({ emitEvent: false });
|
? this.dateInputControl.disable({ emitEvent: false })
|
||||||
}
|
: this.dateInputControl.enable({ emitEvent: false });
|
||||||
|
|
||||||
this.dateInputControl.updateValueAndValidity({ emitEvent: false });
|
this.dateInputControl.updateValueAndValidity({ emitEvent: false });
|
||||||
}
|
}
|
||||||
|
@@ -24,6 +24,7 @@ import {
|
|||||||
FormFieldOption,
|
FormFieldOption,
|
||||||
FormFieldTypes,
|
FormFieldTypes,
|
||||||
FormService,
|
FormService,
|
||||||
|
ReactiveFormWidget,
|
||||||
RuleEntry,
|
RuleEntry,
|
||||||
SelectFilterInputComponent,
|
SelectFilterInputComponent,
|
||||||
WidgetComponent
|
WidgetComponent
|
||||||
@@ -66,10 +67,11 @@ export const HIDE_FILTER_LIMIT = 5;
|
|||||||
SelectFilterInputComponent
|
SelectFilterInputComponent
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class DropdownCloudWidgetComponent extends WidgetComponent implements OnInit {
|
export class DropdownCloudWidgetComponent extends WidgetComponent implements OnInit, ReactiveFormWidget {
|
||||||
public formService = inject(FormService);
|
public formService = inject(FormService);
|
||||||
private formCloudService = inject(FormCloudService);
|
private formCloudService = inject(FormCloudService);
|
||||||
private appConfig = inject(AppConfigService);
|
private appConfig = inject(AppConfigService);
|
||||||
|
private destroyRef = inject(DestroyRef);
|
||||||
|
|
||||||
typeId = 'DropdownCloudWidgetComponent';
|
typeId = 'DropdownCloudWidgetComponent';
|
||||||
showInputFilter = false;
|
showInputFilter = false;
|
||||||
@@ -85,7 +87,6 @@ export class DropdownCloudWidgetComponent extends WidgetComponent implements OnI
|
|||||||
private readonly defaultVariableOptionId = 'id';
|
private readonly defaultVariableOptionId = 'id';
|
||||||
private readonly defaultVariableOptionLabel = 'name';
|
private readonly defaultVariableOptionLabel = 'name';
|
||||||
private readonly defaultVariableOptionPath = 'data';
|
private readonly defaultVariableOptionPath = 'data';
|
||||||
private readonly destroyRef = inject(DestroyRef);
|
|
||||||
|
|
||||||
get showRequiredMessage(): boolean {
|
get showRequiredMessage(): boolean {
|
||||||
return this.dropdownControl.touched && this.dropdownControl.errors?.required && !this.isRestApiFailed && !this.variableOptionsFailed;
|
return this.dropdownControl.touched && this.dropdownControl.errors?.required && !this.isRestApiFailed && !this.variableOptionsFailed;
|
||||||
@@ -133,6 +134,11 @@ export class DropdownCloudWidgetComponent extends WidgetComponent implements OnI
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateReactiveFormControl(): void {
|
||||||
|
this.updateFormControlState();
|
||||||
|
this.handleErrors();
|
||||||
|
}
|
||||||
|
|
||||||
compareDropdownValues(opt1: FormFieldOption | string, opt2: FormFieldOption | string): boolean {
|
compareDropdownValues(opt1: FormFieldOption | string, opt2: FormFieldOption | string): boolean {
|
||||||
if (!opt1 || !opt2) {
|
if (!opt1 || !opt2) {
|
||||||
return false;
|
return false;
|
||||||
@@ -165,19 +171,14 @@ export class DropdownCloudWidgetComponent extends WidgetComponent implements OnI
|
|||||||
this.checkFieldOptionsSource();
|
this.checkFieldOptionsSource();
|
||||||
this.updateOptions();
|
this.updateOptions();
|
||||||
|
|
||||||
this.initFormControl();
|
this.setFormControlValue();
|
||||||
|
this.updateFormControlState();
|
||||||
|
this.subscribeToInputChanges();
|
||||||
this.initFilter();
|
this.initFilter();
|
||||||
|
this.handleErrors();
|
||||||
}
|
}
|
||||||
|
|
||||||
private initFormControl(): void {
|
private subscribeToInputChanges(): void {
|
||||||
if (this.field?.required) {
|
|
||||||
this.dropdownControl.addValidators([Validators.required]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.field?.readOnly || this.readOnly) {
|
|
||||||
this.dropdownControl.disable({ emitEvent: false });
|
|
||||||
}
|
|
||||||
|
|
||||||
this.dropdownControl.valueChanges
|
this.dropdownControl.valueChanges
|
||||||
.pipe(
|
.pipe(
|
||||||
filter(() => !!this.field),
|
filter(() => !!this.field),
|
||||||
@@ -188,19 +189,31 @@ export class DropdownCloudWidgetComponent extends WidgetComponent implements OnI
|
|||||||
this.handleErrors();
|
this.handleErrors();
|
||||||
this.selectionChangedForField(this.field);
|
this.selectionChangedForField(this.field);
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private setFormControlValue(): void {
|
||||||
this.dropdownControl.setValue(this.field?.value, { emitEvent: false });
|
this.dropdownControl.setValue(this.field?.value, { emitEvent: false });
|
||||||
this.handleErrors();
|
}
|
||||||
|
|
||||||
|
private updateFormControlState(): void {
|
||||||
|
this.dropdownControl.setValidators(this.isRequired() ? [Validators.required] : []);
|
||||||
|
this.field?.readOnly || this.readOnly
|
||||||
|
? this.dropdownControl.disable({ emitEvent: false })
|
||||||
|
: this.dropdownControl.enable({ emitEvent: false });
|
||||||
|
|
||||||
|
this.dropdownControl.updateValueAndValidity({ emitEvent: false });
|
||||||
}
|
}
|
||||||
|
|
||||||
private handleErrors(): void {
|
private handleErrors(): void {
|
||||||
if (this.dropdownControl.valid) {
|
if (this.dropdownControl.valid) {
|
||||||
this.field.validationSummary = new ErrorMessageModel('');
|
this.field.validationSummary = new ErrorMessageModel('');
|
||||||
|
this.field.markAsValid();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.dropdownControl.invalid && this.dropdownControl.errors.required) {
|
if (this.dropdownControl.invalid && this.dropdownControl.errors.required) {
|
||||||
this.field.validationSummary = new ErrorMessageModel({ message: 'FORM.FIELD.REQUIRED' });
|
this.field.validationSummary = new ErrorMessageModel({ message: 'FORM.FIELD.REQUIRED' });
|
||||||
|
this.field.markAsInvalid();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -19,12 +19,13 @@
|
|||||||
|
|
||||||
import { Component, DestroyRef, inject, OnInit, ViewEncapsulation } from '@angular/core';
|
import { Component, DestroyRef, inject, OnInit, ViewEncapsulation } from '@angular/core';
|
||||||
import {
|
import {
|
||||||
ErrorMessageModel,
|
|
||||||
ErrorWidgetComponent,
|
|
||||||
FormFieldModel,
|
|
||||||
FormFieldOption,
|
|
||||||
FormService,
|
FormService,
|
||||||
WidgetComponent
|
FormFieldOption,
|
||||||
|
WidgetComponent,
|
||||||
|
ErrorWidgetComponent,
|
||||||
|
ErrorMessageModel,
|
||||||
|
FormFieldModel,
|
||||||
|
ReactiveFormWidget
|
||||||
} from '@alfresco/adf-core';
|
} from '@alfresco/adf-core';
|
||||||
import { ProcessDefinitionService } from '../../services/process-definition.service';
|
import { ProcessDefinitionService } from '../../services/process-definition.service';
|
||||||
import { TaskFormService } from '../../services/task-form.service';
|
import { TaskFormService } from '../../services/task-form.service';
|
||||||
@@ -55,15 +56,14 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|||||||
},
|
},
|
||||||
encapsulation: ViewEncapsulation.None
|
encapsulation: ViewEncapsulation.None
|
||||||
})
|
})
|
||||||
export class DropdownWidgetComponent extends WidgetComponent implements OnInit {
|
export class DropdownWidgetComponent extends WidgetComponent implements OnInit, ReactiveFormWidget {
|
||||||
public formsService = inject(FormService);
|
public formService = inject(FormService);
|
||||||
public taskFormService = inject(TaskFormService);
|
public taskFormService = inject(TaskFormService);
|
||||||
public processDefinitionService = inject(ProcessDefinitionService);
|
public processDefinitionService = inject(ProcessDefinitionService);
|
||||||
|
private readonly destroyRef = inject(DestroyRef);
|
||||||
|
|
||||||
dropdownControl = new FormControl<FormFieldOption | string>(undefined);
|
dropdownControl = new FormControl<FormFieldOption | string>(undefined);
|
||||||
|
|
||||||
private readonly destroyRef = inject(DestroyRef);
|
|
||||||
|
|
||||||
get isReadOnlyType(): boolean {
|
get isReadOnlyType(): boolean {
|
||||||
return this.field.type === 'readonly';
|
return this.field.type === 'readonly';
|
||||||
}
|
}
|
||||||
@@ -93,7 +93,15 @@ export class DropdownWidgetComponent extends WidgetComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.initFormControl();
|
this.setFormControlValue();
|
||||||
|
this.updateFormControlState();
|
||||||
|
this.subscribeToInputChanges();
|
||||||
|
this.handleErrors();
|
||||||
|
}
|
||||||
|
|
||||||
|
updateReactiveFormControl(): void {
|
||||||
|
this.updateFormControlState();
|
||||||
|
this.handleErrors();
|
||||||
}
|
}
|
||||||
|
|
||||||
getValuesByTaskId() {
|
getValuesByTaskId() {
|
||||||
@@ -124,15 +132,7 @@ export class DropdownWidgetComponent extends WidgetComponent implements OnInit {
|
|||||||
return !!this.field?.form?.readOnly;
|
return !!this.field?.form?.readOnly;
|
||||||
}
|
}
|
||||||
|
|
||||||
private initFormControl() {
|
private subscribeToInputChanges(): void {
|
||||||
if (this.field?.required) {
|
|
||||||
this.dropdownControl.addValidators([this.customRequiredValidator(this.field)]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.field?.readOnly || this.readOnly) {
|
|
||||||
this.dropdownControl.disable({ emitEvent: false });
|
|
||||||
}
|
|
||||||
|
|
||||||
this.dropdownControl.valueChanges
|
this.dropdownControl.valueChanges
|
||||||
.pipe(
|
.pipe(
|
||||||
filter(() => !!this.field),
|
filter(() => !!this.field),
|
||||||
@@ -143,9 +143,19 @@ export class DropdownWidgetComponent extends WidgetComponent implements OnInit {
|
|||||||
this.handleErrors();
|
this.handleErrors();
|
||||||
this.onFieldChanged(this.field);
|
this.onFieldChanged(this.field);
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private setFormControlValue(): void {
|
||||||
this.dropdownControl.setValue(this.getOptionValue(this.field?.value), { emitEvent: false });
|
this.dropdownControl.setValue(this.getOptionValue(this.field?.value), { emitEvent: false });
|
||||||
this.handleErrors();
|
}
|
||||||
|
|
||||||
|
private updateFormControlState(): void {
|
||||||
|
this.dropdownControl.setValidators(this.isRequired() ? [this.customRequiredValidator(this.field)] : []);
|
||||||
|
this.field?.readOnly || this.readOnly
|
||||||
|
? this.dropdownControl.disable({ emitEvent: false })
|
||||||
|
: this.dropdownControl.enable({ emitEvent: false });
|
||||||
|
|
||||||
|
this.dropdownControl.updateValueAndValidity({ emitEvent: false });
|
||||||
}
|
}
|
||||||
|
|
||||||
private handleErrors() {
|
private handleErrors() {
|
||||||
@@ -155,11 +165,13 @@ export class DropdownWidgetComponent extends WidgetComponent implements OnInit {
|
|||||||
|
|
||||||
if (this.dropdownControl.valid) {
|
if (this.dropdownControl.valid) {
|
||||||
this.field.validationSummary = new ErrorMessageModel('');
|
this.field.validationSummary = new ErrorMessageModel('');
|
||||||
|
this.field.markAsValid();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.dropdownControl.invalid && this.dropdownControl.errors.required) {
|
if (this.dropdownControl.invalid && this.dropdownControl.errors.required) {
|
||||||
this.field.validationSummary = new ErrorMessageModel({ message: 'FORM.FIELD.REQUIRED' });
|
this.field.validationSummary = new ErrorMessageModel({ message: 'FORM.FIELD.REQUIRED' });
|
||||||
|
this.field.markAsInvalid();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user