From 74252797b75f8fe11276acc97c56f4fa1c67be02 Mon Sep 17 00:00:00 2001 From: Darren Thornton <6361057+dthornton-hyl@users.noreply.github.com> Date: Wed, 1 Apr 2026 13:32:30 -0500 Subject: [PATCH] AAE-28918 Fix for start process button is enabled when required widgets are read only without value (#11781) * AAE-28918 Fix start process button is enabled when required widgets are read only without value * Apply Copilot review suggestions. * updates after code review comments * revert change made earlier --- .../widgets/core/form-field.model.spec.ts | 60 +++++++++++++++++-- .../widgets/core/form-field.model.ts | 17 ++---- 2 files changed, 60 insertions(+), 17 deletions(-) diff --git a/lib/core/src/lib/form/components/widgets/core/form-field.model.spec.ts b/lib/core/src/lib/form/components/widgets/core/form-field.model.spec.ts index 58650e2203..549cacf2e9 100644 --- a/lib/core/src/lib/form/components/widgets/core/form-field.model.spec.ts +++ b/lib/core/src/lib/form/components/widgets/core/form-field.model.spec.ts @@ -1220,7 +1220,7 @@ describe('FormFieldModel', () => { }); }); - it('should validate readOnly field if it is validatable', () => { + it('should fail validation for readOnly required display-external-property field with null value', () => { const form = new FormModel(); const field = new FormFieldModel(form, { id: 'mockDisplayExternalPropertyFieldId', @@ -1233,11 +1233,10 @@ describe('FormFieldModel', () => { const validator = new RequiredFieldValidator(); form.fieldValidators = [validator]; - expect(FormFieldTypes.isValidatableType(FormFieldTypes.DISPLAY_EXTERNAL_PROPERTY)).toBeTrue(); expect(field.validate()).toBe(false); }); - it('should validate NOT readOnly field if it is validatable', () => { + it('should fail validation for required display-external-property field with null value', () => { const form = new FormModel(); const field = new FormFieldModel(form, { id: 'mockDisplayExternalPropertyFieldId', @@ -1250,11 +1249,10 @@ describe('FormFieldModel', () => { const validator = new RequiredFieldValidator(); form.fieldValidators = [validator]; - expect(FormFieldTypes.isValidatableType(FormFieldTypes.DISPLAY_EXTERNAL_PROPERTY)).toBeTrue(); expect(field.validate()).toBe(false); }); - it('should NOT validate readOnly field if it is NOT validatable', () => { + it('should fail validation for readOnly required text field with null value', () => { const form = new FormModel(); const field = new FormFieldModel(form, { id: 'mockTextFieldId', @@ -1267,10 +1265,60 @@ describe('FormFieldModel', () => { const validator = new RequiredFieldValidator(); form.fieldValidators = [validator]; - expect(FormFieldTypes.isValidatableType(FormFieldTypes.TEXT)).toBeFalse(); + expect(field.validate()).toBe(false); + }); + + it('should pass validation for readOnly required field that has a value', () => { + const form = new FormModel(); + const field = new FormFieldModel(form, { + id: 'mockTextFieldId', + type: FormFieldTypes.TEXT, + readOnly: true, + required: true, + value: 'some value' + }); + + const validator = new RequiredFieldValidator(); + form.fieldValidators = [validator]; + expect(field.validate()).toBe(true); }); + it('should pass validation for readOnly non-required field with null value', () => { + const form = new FormModel(); + const field = new FormFieldModel(form, { + id: 'mockTextFieldId', + type: FormFieldTypes.TEXT, + readOnly: true, + required: false, + value: null + }); + + const validator = new RequiredFieldValidator(); + form.fieldValidators = [validator]; + + expect(field.validate()).toBe(true); + }); + + it('should pass validation for readOnly required field with empty value when field or parent is hidden', () => { + const form = new FormModel(); + const field = new FormFieldModel(form, { + id: 'mockTextFieldId', + type: FormFieldTypes.TEXT, + readOnly: true, + required: true, + value: null + }); + + const validator = new RequiredFieldValidator(); + form.fieldValidators = [validator]; + + spyOn(form, 'isFieldOrParentHidden').and.returnValue(true); + + expect(field.validate()).toBe(true); + expect(form.isFieldOrParentHidden).toHaveBeenCalledWith(field); + }); + it('should set the tooltip correctly', () => { const form = new FormModel(); const tooltipText = 'This is a tooltip'; 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 df27122eb9..17da6ad85f 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 @@ -170,23 +170,18 @@ export class FormFieldModel extends FormWidgetModel { validate(): boolean { this.validationSummary = new ErrorMessageModel(); - if (this.isFieldValidatable()) { - const validators = this.form.fieldValidators || []; - for (const validator of validators) { - if (!validator.validate(this)) { - this._isValid = false; - return this._isValid; - } + const validators = this.form?.fieldValidators || []; + for (const validator of validators) { + if (!validator.validate(this)) { + this._isValid = false; + return this._isValid; } } + this._isValid = true; return this._isValid; } - private isFieldValidatable(): boolean { - return !this.readOnly || FormFieldTypes.isValidatableType(this.type); - } - constructor(form: any, json?: any, parent?: RepeatableSectionModel) { super(form, json); if (json) {