Skip to content

Commit

Permalink
AAE-24007 Display radio buttons and dropdown options depending on opt…
Browse files Browse the repository at this point in the history
…ionType (#9975)

* AAE-24007 Update form-field.moel

* AAE-24007 Update dropdown-cloud.widget

* AAE-24007 Update radio-buttons-cloud.widget

* AAE-24007 Dropdown aligment (undefined value should be reserved for empty option)

* AAE-24007 Minor update

* AAE-24007 Update tests

* AAE-24007 Update

* AAE-24007 Update

* AAE-24007 Update

* AAE-24007 Fix units

* AAE-24007 Fix

* AAE-24007 Align standard dropdown and radio
  • Loading branch information
wiktord2000 authored Aug 6, 2024
1 parent 3406341 commit cb0b072
Show file tree
Hide file tree
Showing 10 changed files with 264 additions and 139 deletions.
248 changes: 143 additions & 105 deletions lib/core/src/lib/form/components/widgets/core/form-field.model.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,31 @@ describe('FormFieldModel', () => {
expect(field.readOnly).toBeTruthy();
});

describe('option type property', () => {
const staticOptions = [
{ id: 'op1', name: 'Option 1' },
{ id: 'op2', name: 'Option 2' }
];

it('should assign static options array to options in case of manual type', () => {
const field = new FormFieldModel(new FormModel(), {
optionType: 'manual',
options: staticOptions
});

expect(field.options).toEqual(staticOptions);
});

it('should assign empty array to options in case of rest type', () => {
const field = new FormFieldModel(new FormModel(), {
optionType: 'rest',
options: staticOptions
});

expect(field.options).toEqual([]);
});
});

describe('dropdown field model instantiation', () => {
it('should add value (selected option) to field options if NOT present', () => {
const field = new FormFieldModel(new FormModel(), {
Expand All @@ -137,7 +162,6 @@ describe('FormFieldModel', () => {
});

expect(field.options).toEqual(selectedOptions);
expect(field.value).toEqual(selectedOptions);
});

it('should assign "empty" option as value if value is null and "empty" option is present in options', () => {
Expand Down Expand Up @@ -532,7 +556,7 @@ describe('FormFieldModel', () => {
expect(field.value).toBeFalsy();
});

it('should return the label of selected dropdown value ', () => {
it('should return the label of selected dropdown value', () => {
const field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.DROPDOWN,
options: [
Expand Down Expand Up @@ -702,15 +726,19 @@ describe('FormFieldModel', () => {
id: 'rest-radio',
type: FormFieldTypes.RADIO_BUTTONS,
optionType: 'rest',
options: [
{ id: 'restOpt1', name: 'Rest Option 1' },
{ id: 'restOpt2', name: 'Rest Option 2' }
]
restUrl: 'fake-url',
options: []
});

field.options = [
{ id: 'restOpt1', name: 'Rest Option 1' },
{ id: 'restOpt2', name: 'Rest Option 2' }
];
});

it('should update form with selected option and options from which we chose', () => {
field.value = 'restOpt2';
field.updateForm();

expect(form.values['rest-radio']).toEqual({
id: 'restOpt2',
Expand All @@ -722,6 +750,7 @@ describe('FormFieldModel', () => {
describe('should update form with selected option properties set to null and options from which we chose', () => {
it('when value does NOT match any option', () => {
field.value = 'not_exist';
field.updateForm();

expect(form.values['rest-radio']).toEqual({
id: null,
Expand All @@ -732,6 +761,7 @@ describe('FormFieldModel', () => {

it('when radio button value is null', () => {
field.value = null;
field.updateForm();

expect(form.values['rest-radio']).toEqual({
id: null,
Expand Down Expand Up @@ -863,115 +893,123 @@ describe('FormFieldModel', () => {
expect(form.values['header_field']).not.toBeDefined();
});

it('dropdown field type should appear into form values', () => {
const form = new FormModel();
const field = new FormFieldModel(form, {
fieldType: 'HeaderFieldtype',
id: 'dropdown_field',
name: 'header',
type: FormFieldTypes.DROPDOWN,
value: 'opt1',
required: false,
readOnly: true,
options: [
{ id: 'opt1', name: 'Option 1' },
{ id: 'opt2', name: 'Option 2' }
]
describe('dropdown field', () => {
const getFieldConfig = (optionType, options, value) =>
new FormFieldModel(new FormModel(), {
id: 'dropdown_field',
name: 'dropdown',
type: FormFieldTypes.DROPDOWN,
optionType,
options,
value,
required: false,
restUrl: 'fake-url',
restIdProperty: 'fake-id-property',
restLabelProperty: 'fake-label-property',
restResponsePath: 'fake-response-path'
});

const staticOptions = [
{ id: 'opt1', name: 'Option 1' },
{ id: 'opt2', name: 'Option 2' }
];

it('should assign rest properties properly', () => {
const field = getFieldConfig('rest', [], 'delayed-rest-option-id');

field.updateForm();

expect(field.value).toEqual('delayed-rest-option-id');
expect(field.form.values['dropdown_field']).toEqual(null);
expect(field.restUrl).toEqual('fake-url');
expect(field.restIdProperty).toEqual('fake-id-property');
expect(field.restLabelProperty).toEqual('fake-label-property');
expect(field.restResponsePath).toEqual('fake-response-path');
});
field.updateForm();
expect(form.values['dropdown_field'].name).toEqual('Option 1');
});

it('dropdown field type should be formatted on rest properties', () => {
const form = new FormModel();
const field = new FormFieldModel(form, {
fieldType: 'HeaderFieldtype',
id: 'dropdown_field',
name: 'header',
type: FormFieldTypes.DROPDOWN,
value: 'opt1',
required: false,
readOnly: true,
restUrl: 'fake-url-just-to-show',
optionType: 'rest',
restIdProperty: 'fake-id-property',
restLabelProperty: 'fake-label-property',
options: [
{ id: 'opt1', name: 'Option 1' },
{ id: 'opt2', name: 'Option 2' }
]
it('should NOT consider the static list of options in case of rest type', () => {
const field = getFieldConfig('rest', staticOptions, 'delayed-rest-option-id');

field.updateForm();

expect(field.value).toEqual('delayed-rest-option-id');
expect(field.form.values['dropdown_field']).toEqual(null);
expect(field.options).toEqual([]);
});
field.updateForm();
expect(form.values['dropdown_field'].id).toEqual('opt1');
expect(form.values['dropdown_field'].name).toEqual('Option 1');
});

it('dropdown field type should be formatted on id and name properties if rest properties are not set', () => {
const form = new FormModel();
const field = new FormFieldModel(form, {
fieldType: 'HeaderFieldtype',
id: 'dropdown_field',
name: 'header',
type: FormFieldTypes.DROPDOWN,
value: 'opt1',
required: false,
readOnly: true,
restUrl: 'fake-url-just-to-show',
optionType: 'rest',
options: [
{ id: 'opt1', name: 'Option 1' },
{ id: 'opt2', name: 'Option 2' }
]
it('should consider the static list of options in case of manual type', () => {
const field = getFieldConfig('manual', staticOptions, '');

field.updateForm();

expect(field.value).toEqual('');
expect(field.form.values['dropdown_field']).toEqual(null);
expect(field.options).toEqual(staticOptions);
});
field.updateForm();
expect(form.values['dropdown_field']['id']).toEqual('opt1');
expect(form.values['dropdown_field']['name']).toEqual('Option 1');
});

it('radio button field rest type should appear with its configured label and id into the rest values', () => {
const form = new FormModel();
const field = new FormFieldModel(form, {
fieldType: 'HeaderFieldtype',
id: 'radio_bananan_field',
name: 'banana',
type: FormFieldTypes.RADIO_BUTTONS,
value: 'opt1',
required: false,
readOnly: true,
restUrl: '<whatever-url-you-like-we-do-not-mind>',
restIdProperty: 'banana',
restLabelProperty: 'banLabel',
optionType: 'rest',
options: [
{ id: 'opt1', name: 'Option 1' },
{ id: 'opt2', name: 'Option 2' }
]
it('should selected option appear in form values', () => {
const field = getFieldConfig('manual', staticOptions, 'opt2');

field.updateForm();

expect(field.value).toEqual('opt2');
expect(field.form.values['dropdown_field']).toEqual({ id: 'opt2', name: 'Option 2' });
});
field.updateForm();
expect(form.values['radio_bananan_field'].id).toEqual('opt1');
expect(form.values['radio_bananan_field'].name).toEqual('Option 1');
});

it('radio button field rest type should appear with id / name properties when rest properties are not configured', () => {
const form = new FormModel();
const field = new FormFieldModel(form, {
fieldType: 'HeaderFieldtype',
id: 'radio_bananan_field',
name: 'banana',
type: FormFieldTypes.RADIO_BUTTONS,
value: 'opt1',
required: false,
readOnly: true,
restUrl: '<whatever-url-you-like-we-do-not-mind>',
optionType: 'rest',
options: [
{ id: 'opt1', name: 'Option 1' },
{ id: 'opt2', name: 'Option 2' }
]
describe('radio buttons field', () => {
const getFieldConfig = (optionType, options, value) =>
new FormFieldModel(new FormModel(), {
id: 'radio_field',
name: 'radio',
type: FormFieldTypes.RADIO_BUTTONS,
optionType,
options,
value,
required: false,
restUrl: 'fake-url',
restIdProperty: 'fake-id-property',
restLabelProperty: 'fake-label-property',
restResponsePath: 'fake-response-path'
});

const staticOptions = [
{ id: 'opt1', name: 'Option 1' },
{ id: 'opt2', name: 'Option 2' }
];

it('should assign rest properties properly', () => {
const field = getFieldConfig('rest', [], 'delayed-rest-option-id');

field.updateForm();

expect(field.value).toEqual('delayed-rest-option-id');
expect(field.form.values['radio_field']).toEqual({ id: null, name: null, options: [] });
expect(field.restUrl).toEqual('fake-url');
expect(field.restIdProperty).toEqual('fake-id-property');
expect(field.restLabelProperty).toEqual('fake-label-property');
expect(field.restResponsePath).toEqual('fake-response-path');
});

it('should NOT consider the static list of options in case of rest type', () => {
const field = getFieldConfig('rest', staticOptions, 'delayed-rest-option-id');

field.updateForm();

expect(field.value).toEqual('delayed-rest-option-id');
expect(field.form.values['radio_field']).toEqual({ id: null, name: null, options: [] });
expect(field.options).toEqual([]);
});

it('should consider the static list of options in case of manual type', () => {
const field = getFieldConfig('manual', staticOptions, 'opt1');

field.updateForm();

expect(field.value).toEqual('opt1');
expect(field.form.values['radio_field']).toEqual({ id: 'opt1', name: 'Option 1' });
expect(field.options).toEqual(staticOptions);
});
field.updateForm();
expect(form.values['radio_bananan_field']['id']).toEqual('opt1');
expect(form.values['radio_bananan_field']['name']).toEqual('Option 1');
});

it('should parse and resolve people null value as null', () => {
Expand Down
23 changes: 15 additions & 8 deletions lib/core/src/lib/form/components/widgets/core/form-field.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ import { DataColumn } from '../../../../datatable/data/data-column.model';
import { DateFnsUtils } from '../../../../common';
import { isValid as isValidDate } from 'date-fns';

export type FieldOptionType = 'rest' | 'manual' | 'variable';
export type FieldSelectionType = 'single' | 'multiple';
export type FieldAlignmentType = 'vertical' | 'horizontal';

// Maps to FormFieldRepresentation
export class FormFieldModel extends FormWidgetModel {
private _value: string;
Expand Down Expand Up @@ -71,7 +75,7 @@ export class FormFieldModel extends FormWidgetModel {
restLabelProperty: string;
hasEmptyValue: boolean;
className: string;
optionType: 'rest' | 'manual' | 'variable';
optionType: FieldOptionType;
params: FormFieldMetadata = {};
hyperlinkUrl: string;
displayText: string;
Expand All @@ -80,8 +84,8 @@ export class FormFieldModel extends FormWidgetModel {
enableFractions: boolean = false;
currency: string = null;
dateDisplayFormat: string = this.defaultDateFormat;
selectionType: 'single' | 'multiple' = null;
alignmentType: 'vertical' | 'horizontal' = null;
selectionType: FieldSelectionType;
alignmentType: FieldAlignmentType;
rule?: FormFieldRule;
selectLoggedUser: boolean;
groupsRestriction: string[];
Expand Down Expand Up @@ -193,7 +197,7 @@ export class FormFieldModel extends FormWidgetModel {
this.maxDateRangeValue = json.maxDateRangeValue;
this.dynamicDateRangeSelection = json.dynamicDateRangeSelection;
this.regexPattern = json.regexPattern;
this.options = this.parseValidOptions(json.options);
this.options = this.parseOptions(json.options, json.optionType);
this.emptyOption = this.getEmptyOption(this.options);
this.hasEmptyValue = json?.hasEmptyValue ?? !!this.emptyOption;
this.className = json.className;
Expand Down Expand Up @@ -422,10 +426,9 @@ export class FormFieldModel extends FormWidgetModel {
break;
}

const entry: FormFieldOption[] = this.options.filter((opt) => opt.id === this.value);
if (entry.length > 0) {
this.form.values[this.id] = entry[0];
}
const matchingOption: FormFieldOption = this.options.find((opt) => opt.id === this.value);

this.form.values[this.id] = matchingOption || null;
}
break;
}
Expand Down Expand Up @@ -567,6 +570,10 @@ export class FormFieldModel extends FormWidgetModel {
return Array.isArray(options) ? options.filter((option) => this.isValidOption(option)) : [];
}

private parseOptions(options: any, optionType: FieldOptionType): FormFieldOption[] {
return optionType === 'rest' ? [] : this.parseValidOptions(options);
}

private isValidOption(option: any): boolean {
return typeof option === 'object' && !Array.isArray(option) && option?.id && option?.name;
}
Expand Down
Loading

0 comments on commit cb0b072

Please sign in to comment.