AAE-43881 Fix for form rules not applying when new [data] comes in (#11879)

This commit is contained in:
Alex Molodyh
2026-05-20 14:19:30 +05:30
committed by Anamika Dey
parent 891d0a37e6
commit 6d2e64fb6e
6 changed files with 426 additions and 18 deletions
@@ -4,7 +4,7 @@
@if (hasTabs()) {
<div class="alfresco-tabs-widget">
<mat-tab-group [preserveContent]="true">
@for (tab of visibleTabs(); track tab) {
@for (tab of visibleTabs(); track tab.id) {
<mat-tab [label]="tab.title | translate ">
<ng-template matTabContent>
<div class="adf-form-tab-content">
@@ -26,7 +26,7 @@
</div>
<ng-template #render let-fieldToRender="fieldToRender">
@for (currentRootElement of fieldToRender; track currentRootElement) {
@for (currentRootElement of fieldToRender; track currentRootElement.id) {
@if (currentRootElement.type === 'section') {
<div [id]="'field-' + currentRootElement?.id + '-container'" class="adf-container-widget">
<adf-form-section [field]="currentRootElement.field" />
@@ -1,13 +1,13 @@
<div class="adf-grid-list-section-single-column"
[id]="'field-' + field?.id + '-container'"
[style.display]="field?.isVisible ? 'flex' : 'none'">
@for (sectionColumn of field.columns; track sectionColumn; let columnIndex = $index) {
<div [style.width.%]="getSectionColumnWidth(field.numberOfColumns, field.columns, columnIndex)">
@for (sectionField of sectionColumn.fields; track sectionField) {
<div class="adf-grid-list-section-column-view-item">
<adf-form-field [field]="sectionField"/>
</div>
}
</div>
@for (sectionColumn of field.columns; track sectionColumn.id; let columnIndex = $index) {
<div [style.width.%]="getSectionColumnWidth(field.numberOfColumns, field.columns, columnIndex)">
@for (sectionField of sectionColumn.fields; track sectionField) {
<div class="adf-grid-list-section-column-view-item">
<adf-form-field [field]="sectionField"/>
</div>
}
</div>
}
</div>
@@ -1757,4 +1757,69 @@ describe('FormFieldModel', () => {
});
});
});
describe('restoreRuntimeValue', () => {
it('should set _value and write to form.values for a top-level text field', () => {
const form = new FormModel();
const field = new FormFieldModel(form, { id: 'text1', type: 'text', value: null });
field.restoreRuntimeValue('restored');
expect(field.value).toBe('restored');
expect(form.values['text1']).toBe('restored');
});
it('should not call onFormFieldChanged unlike updateForm', () => {
const form = new FormModel();
const field = new FormFieldModel(form, { id: 'text1', type: 'text', value: null });
spyOn(form, 'onFormFieldChanged');
field.restoreRuntimeValue('restored');
expect(form.onFormFieldChanged).not.toHaveBeenCalled();
});
it('should resolve dropdown option object from string id via getFormValue', () => {
const form = new FormModel();
const field = new FormFieldModel(form, {
id: 'dd1',
type: 'dropdown',
optionType: 'manual',
options: [
{ id: 'opt1', name: 'Option 1' },
{ id: 'opt2', name: 'Option 2' }
],
value: null
});
field.restoreRuntimeValue('opt1');
expect(form.values['dd1']).toEqual({ id: 'opt1', name: 'Option 1' });
});
it('should set form.values to null when dropdown option id does not match any option', () => {
const form = new FormModel();
const field = new FormFieldModel(form, {
id: 'dd1',
type: 'dropdown',
optionType: 'manual',
options: [{ id: 'opt1', name: 'Option 1' }],
value: null
});
field.restoreRuntimeValue('nonexistent');
expect(form.values['dd1']).toBeNull();
});
it('should not update form.values when resolved value is undefined', () => {
const form = new FormModel();
form.values['text1'] = 'existing';
const field = new FormFieldModel(form, { id: 'text1', type: 'text', value: 'existing' });
field.restoreRuntimeValue(undefined);
expect(form.values['text1']).toBe('existing');
});
});
});
@@ -607,6 +607,21 @@ export class FormFieldModel extends FormWidgetModel {
this.form.onFormFieldChanged(this);
}
restoreRuntimeValue(value: any): void {
this._value = value;
const formValue = this.getFormValue();
if (this.parent) {
this.updateRepeatableSectionValue(formValue);
} else {
this.updateValue(formValue);
}
}
restoreRuntimeFlags(required: boolean, readOnly: boolean): void {
this._required = required;
this._readOnly = readOnly;
}
getFormValue() {
switch (this.type) {
case FormFieldTypes.DROPDOWN: {