AAE-22947 Update form-field.model

This commit is contained in:
wiktord2000 2024-06-11 09:55:45 +02:00
parent 7c2aeb060b
commit 44e2911eaf
No known key found for this signature in database
2 changed files with 107 additions and 70 deletions

View File

@ -115,11 +115,66 @@ describe('FormFieldModel', () => {
it('should parse and leave dropdown value as is', () => {
const field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.DROPDOWN,
options: [],
value: 'deferred'
options: [{ id: 'one', name: 'One' }],
value: { id: 'one', name: 'One' }
});
expect(field.value).toBe('deferred');
expect(field.value).toEqual({ id: 'one', name: 'One' });
expect(field.options).toEqual([{ id: 'one', name: 'One' }]);
});
it('should filter out invalid options on field initialization', () => {
const field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.DROPDOWN,
options: [{ id: 'valid', name: 'Valid' }, { id: 'invalid' }, { name: 'invalid' }, [], {}, 'invalid'],
value: null
});
expect(field.options).toEqual([{ id: 'valid', name: 'Valid' }]);
});
it('should add value to field options if NOT present', () => {
const field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.DROPDOWN,
options: [],
value: { id: 'one', name: 'One' }
});
expect(field.value).toEqual({ id: 'one', name: 'One' });
expect(field.options).toEqual([{ id: 'one', name: 'One' }]);
});
it('should assign "empty" option as value if value is null and "empty" option is present in options', () => {
const field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.DROPDOWN,
options: [
{ id: 'empty', name: 'Chose option...' },
{ id: 'one', name: 'One' }
],
value: null
});
expect(field.value).toEqual({ id: 'empty', name: 'Chose option...' });
});
it('should assign null to value when value has invalid option object', () => {
const field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.DROPDOWN,
options: [{ id: 'one', name: 'One' }],
value: { id: 'one' }
});
expect(field.value).toBe(null);
});
it('should set hasEmptyValue to true if "empty" option is present in options', () => {
const field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.DROPDOWN,
options: [{ id: 'empty', name: 'Chose option...' }],
value: null
});
expect(field.hasEmptyValue).toBe(true);
});
it('should add value to field options if NOT present', () => {
@ -144,7 +199,7 @@ describe('FormFieldModel', () => {
});
expect(field.hasEmptyValue).toBe(true);
expect(field.emptyOption).toEqual({ id: 'empty', name: 'Chose one...' });
expect(field.emptyValueOption).toEqual({ id: 'empty', name: 'Chose one...' });
expect(field.value).toEqual('empty');
});
@ -156,7 +211,7 @@ describe('FormFieldModel', () => {
});
expect(field.hasEmptyValue).toBe(true);
expect(field.emptyOption).toEqual({ id: 'empty', name: 'Choose one...' });
expect(field.emptyValueOption).toEqual({ id: 'empty', name: 'Choose one...' });
});
it('should add default "empty" option to the options if hasEmptyValue is true but "empty" option is not present', () => {
@ -168,7 +223,7 @@ describe('FormFieldModel', () => {
});
expect(field.hasEmptyValue).toBe(true);
expect(field.emptyOption).toEqual({ id: 'empty', name: 'Choose one...' });
expect(field.emptyValueOption).toEqual({ id: 'empty', name: 'Choose one...' });
expect(field.options).toEqual([
{ id: 'empty', name: 'Choose one...' },
{ id: 'one', name: 'One' }
@ -495,7 +550,7 @@ describe('FormFieldModel', () => {
{ id: 'fake-option-2', name: 'fake label 2' },
{ id: 'fake-option-3', name: 'fake label 3' }
],
value: 'fake-option-2'
value: { id: 'fake-option-2', name: 'fake label 2' }
});
expect(field.getOptionName()).toBe('fake label 2');
expect(field.hasEmptyValue).toBe(true);
@ -562,20 +617,17 @@ describe('FormFieldModel', () => {
expect(field.value).toBe(false);
});
it('should set the value as null for a dropdown field that has the None value selected', () => {
it('should set the form value as null for a dropdown field that has the "empty" option selected', () => {
const form = new FormModel();
const field = new FormFieldModel(form, {
id: 'dropdown-1',
type: FormFieldTypes.DROPDOWN
type: FormFieldTypes.DROPDOWN,
options: [{ id: 'empty', name: 'Chose option...' }],
value: null
});
field.value = 'empty';
expect(form.values['dropdown-1']).toBe(null);
field.value = '';
expect(form.values['dropdown-1']).toBe(null);
field.value = undefined;
expect(field.hasEmptyValue).toBe(true);
expect(field.value).toEqual({ id: 'empty', name: 'Chose option...' });
expect(form.values['dropdown-1']).toBe(null);
});
@ -590,8 +642,12 @@ describe('FormFieldModel', () => {
]
});
field.value = 'opt2';
expect(form.values['dropdown-2']).toEqual(field.options[1]);
const valueBeforeSelection = form.values['dropdown-2'];
field.value = field.options[1];
const valueAfterSelection = form.values['dropdown-2'];
expect(valueBeforeSelection).toEqual(null);
expect(valueAfterSelection).toEqual({ id: 'opt2', name: 'Option 2' });
});
it('should update form with radio button value', () => {
@ -728,7 +784,7 @@ describe('FormFieldModel', () => {
id: 'dropdown_field',
name: 'header',
type: FormFieldTypes.DROPDOWN,
value: 'opt1',
value: { id: 'opt1', name: 'Option 1' },
required: false,
readOnly: true,
options: [
@ -747,7 +803,7 @@ describe('FormFieldModel', () => {
id: 'dropdown_field',
name: 'header',
type: FormFieldTypes.DROPDOWN,
value: 'opt1',
value: { id: 'opt1', name: 'Option 1' },
required: false,
readOnly: true,
restUrl: 'fake-url-just-to-show',
@ -771,7 +827,7 @@ describe('FormFieldModel', () => {
id: 'dropdown_field',
name: 'header',
type: FormFieldTypes.DROPDOWN,
value: 'opt1',
value: { id: 'opt1', name: 'Option 1' },
required: false,
readOnly: true,
restUrl: 'fake-url-just-to-show',

View File

@ -38,6 +38,7 @@ export class FormFieldModel extends FormWidgetModel {
private _isValid: boolean = true;
private _required: boolean = false;
private readonly emptyValueOptionId = 'empty';
readonly defaultDateFormat: string = 'D-M-YYYY';
readonly defaultDateTimeFormat: string = 'D-M-YYYY hh:mm A';
private readonly defaultEmptyOptionId = 'empty';
@ -96,7 +97,7 @@ export class FormFieldModel extends FormWidgetModel {
columns: ContainerColumnModel[] = [];
// util members
emptyOption: FormFieldOption;
emptyValueOption: FormFieldOption;
validationSummary: ErrorMessageModel;
get value(): any {
@ -189,9 +190,9 @@ export class FormFieldModel extends FormWidgetModel {
this.maxDateRangeValue = json.maxDateRangeValue;
this.dynamicDateRangeSelection = json.dynamicDateRangeSelection;
this.regexPattern = json.regexPattern;
this.options = this.parseValidOptions(json.options);
this.emptyOption = this.getEmptyOption(this.options);
this.hasEmptyValue = json?.hasEmptyValue ?? !!this.emptyOption;
this.options = Array.isArray(json.options) ? json.options.filter((option) => this.isValidOption(option)) : [];
this.hasEmptyValue = json?.hasEmptyValue ?? this.hasEmptyValueOption(this.options);
this.emptyValueOption = this.hasEmptyValue ? this.getEmptyValueOption(this.options) : undefined;
this.className = json.className;
this.optionType = json.optionType;
this.params = json.params || {};
@ -236,8 +237,12 @@ export class FormFieldModel extends FormWidgetModel {
this.updateForm();
}
private getEmptyOption(options: FormFieldOption[]): FormFieldOption {
return options.find((option) => option?.id === this.defaultEmptyOptionId);
private getEmptyValueOption(options: FormFieldOption[]): FormFieldOption {
return options.find((option) => option?.id === this.emptyValueOptionId);
}
private hasEmptyValueOption(options: FormFieldOption[]): boolean {
return options.some((option) => option?.id === this.emptyValueOptionId);
}
private setValueForReadonlyType(form: any) {
@ -304,41 +309,42 @@ export class FormFieldModel extends FormWidgetModel {
/*
This is needed due to Activiti issue related to reading dropdown values as value string
but saving back as object: { id: <id>, name: <name> }
Side note: Probably not valid anymore
*/
if (json.type === FormFieldTypes.DROPDOWN) {
if (this.hasEmptyValue) {
if (!this.emptyOption) {
this.emptyOption = {
if (this.hasEmptyValue && value === null) {
if (!this.emptyValueOption) {
this.emptyValueOption = {
id: this.defaultEmptyOptionId,
name: this.defaultEmptyOptionName
};
this.options.unshift(this.emptyOption);
this.options.unshift(this.emptyValueOption);
}
const isEmptyValue = !value || [this.emptyOption.id, this.emptyOption.name].includes(value);
if (isEmptyValue) {
return this.emptyOption.id;
}
value = this.emptyValueOption;
return value;
}
if (this.isValidOption(value)) {
this.addOption(value);
return value.id;
return value;
}
if (this.hasMultipleValues) {
const validSelectedOptions = (Array.isArray(json.value) ? json.value : []).filter((option) => this.isValidOption(option));
let arrayOfSelectedOptions = Array.isArray(json.value) ? json.value : [];
arrayOfSelectedOptions = arrayOfSelectedOptions.filter((option) => this.isValidOption(option));
this.addOptions(validSelectedOptions);
return validSelectedOptions;
this.addOptions(arrayOfSelectedOptions);
value = arrayOfSelectedOptions;
return value;
}
return value;
return null;
}
/*
This is needed due to Activiti issue related to reading radio button values as value string
but saving back as object: { id: <id>, name: <name> }
Side note: Probably not valid anymore
*/
if (json.type === FormFieldTypes.RADIO_BUTTONS) {
// Activiti has a bug with default radio button value where initial selection passed as `name` value
@ -385,31 +391,7 @@ export class FormFieldModel extends FormWidgetModel {
switch (this.type) {
case FormFieldTypes.DROPDOWN: {
if (!this.value) {
this.form.values[this.id] = null;
break;
}
/*
This is needed due to Activiti reading dropdown values as string
but saving back as object: { id: <id>, name: <name> }
*/
if (Array.isArray(this.value)) {
this.form.values[this.id] = this.value;
break;
}
if (typeof this.value === 'string') {
if (this.value === 'empty' || this.value === '') {
this.form.values[this.id] = null;
break;
}
const entry: FormFieldOption[] = this.options.filter((opt) => opt.id === this.value);
if (entry.length > 0) {
this.form.values[this.id] = entry[0];
}
}
this.form.values[this.id] = this.isEmptyValueOption(this.value) ? null : this.value;
break;
}
case FormFieldTypes.RADIO_BUTTONS: {
@ -509,9 +491,8 @@ export class FormFieldModel extends FormWidgetModel {
return type === 'container';
}
getOptionName(): string {
const option: FormFieldOption = this.options.find((opt) => opt.id === this.value);
return option ? option.name : null;
getOptionName(): null | string {
return this.value ? this.value?.name : null;
}
hasOptions() {
@ -519,7 +500,7 @@ export class FormFieldModel extends FormWidgetModel {
}
isEmptyValueOption(option: FormFieldOption): boolean {
return this.hasEmptyValue && option?.id === this.defaultEmptyOptionId;
return this.hasEmptyValueOption && option?.id === this.emptyValueOptionId;
}
private addOptions(options: FormFieldOption[]) {