[AAE-7010] - Fix nested linked dropdowns are not reset (#7463)

* [AAE-7010] - Fix nested linked dropdowns are not reset

* Rebase

* Reset rest in case value is not part of the options

* Update failing unit test due to form field changes
This commit is contained in:
arditdomi
2022-01-24 13:57:22 +00:00
committed by GitHub
parent bfe2961473
commit e98fd2db0c
4 changed files with 108 additions and 25 deletions

View File

@@ -531,7 +531,7 @@ describe('FormFieldModel', () => {
expect(field.value).toBe(false);
});
it('should update form with empty dropdown value', () => {
it('should delete empty dropdown value from the form values', () => {
const form = new FormModel();
const field = new FormFieldModel(form, {
id: 'dropdown-1',
@@ -539,10 +539,10 @@ describe('FormFieldModel', () => {
});
field.value = 'empty';
expect(form.values['dropdown-1']).toEqual({});
expect(form.values['dropdown-1']).toBe(undefined);
field.value = '';
expect(form.values['dropdown-1']).toEqual({});
expect(form.values['dropdown-1']).toBe(undefined);
});
it('should update form with dropdown value', () => {

View File

@@ -293,17 +293,14 @@ export class FormFieldModel extends FormWidgetModel {
if (json.type === FormFieldTypes.DROPDOWN) {
if (json.options) {
const options = <FormFieldOption[]> json.options || [];
if (options.length > 0) {
if (json.hasEmptyValue) {
const emptyOption = json.options[0];
if (value === '' || value === emptyOption.id || value === emptyOption.name) {
value = emptyOption.id;
}
} else {
if (value?.id && value?.name) {
value = value.id;
}
if (json.hasEmptyValue) {
const emptyOption = json.options[0];
if (value === '' || value === emptyOption.id || value === emptyOption.name) {
value = emptyOption.id;
}
} else {
if (value?.id && value?.name) {
value = value.id;
}
}
}
@@ -371,7 +368,7 @@ export class FormFieldModel extends FormWidgetModel {
if (typeof this.value === 'string') {
if (this.value === 'empty' || this.value === '') {
this.form.values[this.id] = {};
delete this.form.values[this.id];
break;
}

View File

@@ -19,7 +19,7 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { of, throwError } from 'rxjs';
import { DropdownCloudWidgetComponent } from './dropdown-cloud.widget';
import { FormFieldModel, FormModel, FormService, setupTestBed } from '@alfresco/adf-core';
import { FormFieldModel, FormModel, FormService, setupTestBed, FormFieldEvent } from '@alfresco/adf-core';
import { FormCloudService } from '../../../services/form-cloud.service';
import { ProcessServiceCloudTestingModule } from '../../../../testing/process-service-cloud.testing.module';
import { TranslateModule } from '@ngx-translate/core';
@@ -428,6 +428,25 @@ describe('DropdownCloudWidgetComponent', () => {
expect(widget.field.options.length).toBe(2);
expect(failedErrorMsgElement3).toBeNull();
});
describe('Rest - On parent value changes (chain)', () => {
it('should fire a form field value changed event when the value gets reset (notify children on the chain to reset)', () => {
spyOn(formCloudService, 'getRestWidgetData').and.returnValue(throwError('Failed to fetch options'));
widget.field.options = mockConditionalEntries[1].options;
widget.field.value = 'MI';
fixture.detectChanges();
const formFieldValueChangedSpy = spyOn(formService.formFieldValueChanged, 'next').and.callThrough();
const formFieldValueChangedEvent = new FormFieldEvent(widget.field.form, widget.field);
parentDropdown.value = 'GR';
widget.selectionChangedForField(parentDropdown);
fixture.detectChanges();
expect(formFieldValueChangedSpy).toHaveBeenCalledWith(formFieldValueChangedEvent);
expect(widget.field.options).toEqual([]);
});
});
});
describe('Manual options', () => {
@@ -480,6 +499,49 @@ describe('DropdownCloudWidgetComponent', () => {
expect(defaultOption.context.value).toBe('empty');
expect(defaultOption.context.viewValue).toBe('Choose one...');
});
describe('Manual - On parent value changes (chain)', () => {
it('should reset the current value when it not part of the available options', () => {
widget.field.options = mockConditionalEntries[1].options;
widget.field.value = 'non-existent-value';
fixture.detectChanges();
parentDropdown.value = 'GR';
widget.selectionChangedForField(parentDropdown);
fixture.detectChanges();
expect(widget.field.options).toEqual(mockConditionalEntries[0].options);
expect(widget.fieldValue).toEqual('');
});
it('should not reset the current value when it is part of the available options', () => {
widget.field.options = mockConditionalEntries[1].options;
widget.field.value = 'ATH';
fixture.detectChanges();
parentDropdown.value = 'GR';
widget.selectionChangedForField(parentDropdown);
fixture.detectChanges();
expect(widget.field.options).toEqual(mockConditionalEntries[0].options);
expect(widget.fieldValue).toEqual('ATH');
});
it('should fire a form field value changed event when the value gets reset (notify children on the chain to reset)', () => {
widget.field.options = mockConditionalEntries[1].options;
widget.field.value = 'non-existent-value';
fixture.detectChanges();
const formFieldValueChangedSpy = spyOn(formService.formFieldValueChanged, 'next').and.callThrough();
const formFieldValueChangedEvent = new FormFieldEvent(widget.field.form, widget.field);
parentDropdown.value = 'GR';
widget.selectionChangedForField(parentDropdown);
fixture.detectChanges();
expect(formFieldValueChangedSpy).toHaveBeenCalledWith(formFieldValueChangedEvent);
});
});
});
describe('Load selection for linked dropdown (i.e. saved, completed forms)', () => {

View File

@@ -104,6 +104,7 @@ export class DropdownCloudWidgetComponent extends WidgetComponent implements OnI
this.field.options = result;
this.updateOptions();
this.field.updateForm();
this.resetInvalidValue();
}, (err) => {
this.resetRestApiOptions();
this.handleError(err);
@@ -133,18 +134,18 @@ export class DropdownCloudWidgetComponent extends WidgetComponent implements OnI
}
private parentValueChanged(value: string) {
if (this.isValidValue(value)) {
if (value && !this.isDefaultValue(value)) {
this.isValidRestType() ? this.persistFieldOptionsFromRestApi() : this.persistFieldOptionsFromManualList(value);
} else if (this.isDefaultValue(value)) {
this.resetRestApiErrorMessage();
this.addDefaultOption();
this.resetInvalidValue();
} else {
this.field.options = [];
this.resetInvalidValue();
}
}
private isValidValue(value: string): boolean {
return !!value && value !== DropdownCloudWidgetComponent.DEFAULT_OPTION.id;
}
private isDefaultValue(value: string): boolean {
return value === DropdownCloudWidgetComponent.DEFAULT_OPTION.id;
}
@@ -159,13 +160,37 @@ export class DropdownCloudWidgetComponent extends WidgetComponent implements OnI
rulesEntries.forEach((ruleEntry: RuleEntry) => {
if (ruleEntry.key === value) {
this.field.options = ruleEntry.options;
this.updateOptions();
this.field.updateForm();
this.resetInvalidValue();
}
});
}
}
private resetInvalidValue() {
if (!this.isValidValue()) {
this.resetValue();
}
}
private resetValue() {
this.field.value = '';
this.selectionChangedForField(this.field);
this.updateOptions();
this.field.updateForm();
}
private isValidValue(): boolean {
return this.fieldValue && !this.isDefaultValue(this.fieldValue) && this.isSelectedValueInOptions();
}
private isSelectedValueInOptions(): boolean {
return [...this.field.options].map(option => option.id).includes(this.fieldValue);
}
get fieldValue(): string {
return this.field.value;
}
private hasRuleEntries(): boolean {
return !!this.field.rule.entries.length;
}
@@ -269,10 +294,9 @@ export class DropdownCloudWidgetComponent extends WidgetComponent implements OnI
resetRestApiOptions() {
this.field.options = [];
this.resetValue();
this.isRestApiFailed = true;
this.restApiHostName = this.getRestUrlHostName();
this.updateOptions();
this.field.updateForm();
}
private getRestUrlHostName(): string {