AAE-39988 Fix dropdown conditional functionality (#11343)

* AAE-39988 Fix dropdown conditional functionality

* AAE-39988 Add form-field-rule handler
This commit is contained in:
Diogo Bastos
2025-11-17 12:50:44 +00:00
committed by GitHub
parent ac3c30480b
commit a748541ca0
5 changed files with 261 additions and 12 deletions
@@ -1291,6 +1291,38 @@ describe('FormFieldModel', () => {
existingColspan: 1,
maxColspan: 2
}
},
{
id: 'Dropdown0e7tn4',
name: 'Dropdown',
type: 'dropdown',
readOnly: false,
required: false,
colspan: 1,
rowspan: 1,
optionType: 'manual',
options: [
{
id: 'Id_1',
name: 'Label 1'
},
{
id: 'Id_2',
name: 'Label 2'
}
],
authName: null,
restUrl: null,
restResponsePath: null,
restIdProperty: null,
restLabelProperty: null,
selectionType: 'single',
visibilityCondition: null,
params: {
existingColspan: 1,
maxColspan: 2
},
rule: null
}
],
'2': [
@@ -1310,6 +1342,50 @@ describe('FormFieldModel', () => {
existingColspan: 1,
maxColspan: 2
}
},
{
id: 'Dropdown0wgm63',
name: 'Dropdown',
type: 'dropdown',
readOnly: false,
required: false,
colspan: 1,
rowspan: 1,
optionType: 'manual',
options: [],
authName: null,
restUrl: null,
restResponsePath: null,
restIdProperty: null,
restLabelProperty: null,
selectionType: 'single',
visibilityCondition: null,
params: {
existingColspan: 1,
maxColspan: 2
},
rule: {
ruleOn: 'Dropdown0e7tn4',
entries: [
{
key: 'Id_1',
options: [
{
id: 'Id_3',
name: 'Label 3'
},
{
id: 'Id_4',
name: 'Label 4'
}
]
},
{
key: 'Id_2',
options: []
}
]
}
}
]
};
@@ -1544,5 +1620,46 @@ describe('FormFieldModel', () => {
});
});
});
describe('widgets', () => {
describe('id property', () => {
let textWidget: FormFieldModel;
beforeEach(() => {
textWidget = field.rows[0].columns[0].fields[0];
});
it('should set id to parent uid', () => {
expect(textWidget.id).toBe(textWidget.parent.uid);
});
it('should NOT set id to json id', () => {
const textWidgetJson = json.fields['1'][0];
expect(textWidget.id).not.toBe(textWidgetJson.id);
});
});
describe('rule property', () => {
let conditionalDropdown: FormFieldModel;
let targetDropdown: FormFieldModel;
beforeEach(() => {
conditionalDropdown = field.rows[0].columns[1].fields[1];
});
it('should set ruleOn property of rule to target id', () => {
targetDropdown = field.rows[0].columns[0].fields[1];
expect(conditionalDropdown.rule.ruleOn).toBe(targetDropdown.id);
});
it('should NOT set ruleOn property of rule to target json id', () => {
const targetDropdownJson = json.fields['1'][1];
expect(conditionalDropdown.rule.ruleOn).not.toBe(targetDropdownJson.id);
});
});
});
});
});
@@ -31,21 +31,13 @@ import { DataColumn } from '../../../../datatable/data/data-column.model';
import { DateFnsUtils } from '../../../../common';
import { isValid as isValidDate } from 'date-fns';
import { ContainerRowModel } from './container-row.model';
import { RepeatableSectionModel, ROW_ID_PREFIX } from './repeatable-section.model';
import { formFieldRuleHandler } from './handlers/form-field-rule.handler';
export type FieldOptionType = 'rest' | 'manual' | 'variable';
export type FieldSelectionType = 'single' | 'multiple';
export type FieldAlignmentType = 'vertical' | 'horizontal';
interface RepeatableSectionModel {
id: string;
uid: string;
fields: FormFieldModel[];
rowIndex: number;
value?: any;
}
const ROW_ID_PREFIX = '-Row';
// Maps to FormFieldRepresentation
export class FormFieldModel extends FormWidgetModel {
private _value: string;
@@ -195,7 +187,7 @@ export class FormFieldModel extends FormWidgetModel {
super(form, json);
if (json) {
this.fieldType = json.fieldType;
this.id = parent ? parent.uid : json.id;
this.id = this.getId(json.id, parent);
this.name = json.name;
this.type = json.type;
this.roles = json.roles;
@@ -233,7 +225,7 @@ export class FormFieldModel extends FormWidgetModel {
this.tooltip = json.tooltip || '';
this.selectionType = json.selectionType;
this.alignmentType = json.alignmentType;
this.rule = json.rule;
this.rule = formFieldRuleHandler.getRule(this.id, json.rule, parent);
this.selectLoggedUser = json.selectLoggedUser;
this.groupsRestriction = json.groupsRestriction?.groups;
this.variableConfig = json.variableConfig;
@@ -289,6 +281,10 @@ export class FormFieldModel extends FormWidgetModel {
return originalType === FormFieldTypes.DATETIME ? this.defaultDateTimeFormat : this.defaultDateFormat;
}
private getId(id: string, parent?: RepeatableSectionModel): string {
return parent ? parent.uid : id;
}
private isTypeaheadFieldType(type: string): boolean {
return type === 'typeahead';
}
@@ -0,0 +1,69 @@
/*!
* @license
* Copyright © 2005-2025 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 { formFieldRuleHandler } from './form-field-rule.handler';
import { FormFieldRule } from '../form-field-rule';
import { RepeatableSectionModel } from '../repeatable-section.model';
describe('formFieldRuleHandler', () => {
it('should return null if provided rule is null', () => {
expect(formFieldRuleHandler.getRule('mock-id', null)).toBe(null);
});
it('should return undefined if provided rule is undefined', () => {
expect(formFieldRuleHandler.getRule('mock-id', undefined)).toBe(undefined);
});
it('should return provided rule if rule is provided', () => {
const rule: FormFieldRule = {
ruleOn: 'mock-rule-on',
entries: []
};
expect(formFieldRuleHandler.getRule('mock-id', rule)).toEqual(rule);
});
it('should return provided rule if rule is provided and no parent is provided', () => {
const rule: FormFieldRule = {
ruleOn: 'mock-rule-on',
entries: []
};
expect(formFieldRuleHandler.getRule('mock-id', rule)).toEqual(rule);
});
it('should return rule with parent ruleOn property if rule and parent are provided', () => {
const rule: FormFieldRule = {
ruleOn: 'mock-rule-on',
entries: []
};
const parent: RepeatableSectionModel = {
id: 'mock-parent-id',
uid: 'mock-id-Row123456789',
fields: [],
rowIndex: 0
};
const expectedRule: FormFieldRule = {
ruleOn: 'mock-rule-on-Row123456789',
entries: []
};
expect(formFieldRuleHandler.getRule('mock-id-Row123456789', rule, parent)).toEqual(expectedRule);
});
});
@@ -0,0 +1,39 @@
/*!
* @license
* Copyright © 2005-2025 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 { FormFieldRule } from '../form-field-rule';
import { RepeatableSectionModel, ROW_ID_PREFIX } from '../repeatable-section.model';
const getRule = (id: string, rule?: FormFieldRule, parent?: RepeatableSectionModel): FormFieldRule =>
rule && parent
? ({
...rule,
ruleOn: getRepeatableSectionChildRuleOn(id, rule.ruleOn ?? '')
} as FormFieldRule)
: rule;
const getRepeatableSectionChildRuleOn = (id: string, ruleOn: string): string => ruleOn + ROW_ID_PREFIX + getRowId(id);
const getRowId = (id: string) => {
const split = id.split(ROW_ID_PREFIX);
return split.length > 1 ? split[1] : '';
};
export const formFieldRuleHandler = {
getRule
};
@@ -0,0 +1,28 @@
/*!
* @license
* Copyright © 2005-2025 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 { FormFieldModel } from './form-field.model';
export const ROW_ID_PREFIX = '-Row';
export interface RepeatableSectionModel {
id: string;
uid: string;
fields: FormFieldModel[];
rowIndex: number;
value?: any;
}