diff --git a/lib/process-services-cloud/src/lib/form/components/widgets/dropdown/dropdown-cloud.widget.html b/lib/process-services-cloud/src/lib/form/components/widgets/dropdown/dropdown-cloud.widget.html
index 0bf385425e..b45c34b1fd 100644
--- a/lib/process-services-cloud/src/lib/form/components/widgets/dropdown/dropdown-cloud.widget.html
+++ b/lib/process-services-cloud/src/lib/form/components/widgets/dropdown/dropdown-cloud.widget.html
@@ -7,8 +7,8 @@
-
- {{ defaultOption.name }}
+
+ {{ emptyValueOption.name }}
{{opt.name}}
{{field.value}}
diff --git a/lib/process-services-cloud/src/lib/form/components/widgets/dropdown/dropdown-cloud.widget.spec.ts b/lib/process-services-cloud/src/lib/form/components/widgets/dropdown/dropdown-cloud.widget.spec.ts
index cd28d70586..7051924e54 100644
--- a/lib/process-services-cloud/src/lib/form/components/widgets/dropdown/dropdown-cloud.widget.spec.ts
+++ b/lib/process-services-cloud/src/lib/form/components/widgets/dropdown/dropdown-cloud.widget.spec.ts
@@ -179,10 +179,10 @@ describe('DropdownCloudWidgetComponent', () => {
expect(await (await dropdown.getOptions())[0].getText()).toEqual('default1_value');
});
- it('should preselect dropdown widget value when String (defined value) passed ', async () => {
+ it('should preselect dropdown widget value when value matches one of the fetched options', async () => {
widget.field.restUrl = 'https://fake-rest-url';
widget.field.optionType = 'rest';
- widget.field.value = 'opt1';
+ widget.field.value = { id: 'opt1', name: 'default1_value' };
spyOn(formCloudService, 'getRestWidgetData').and.returnValue(
of([
@@ -245,7 +245,7 @@ describe('DropdownCloudWidgetComponent', () => {
await dropdown.clickOptions({ selector: '[id="opt_1"]' });
expect(await dropdown.getValueText()).toEqual('option_1');
- expect(widget.fieldValue).toEqual('opt_1');
+ expect(widget.fieldValue).toEqual({ id: 'opt_1', name: 'option_1' });
await dropdown.open();
await dropdown.clickOptions({ selector: '[id="empty"]' });
@@ -254,8 +254,8 @@ describe('DropdownCloudWidgetComponent', () => {
const dropdownLabel = await formField.getLabel();
expect(dropdownLabel).toEqual('This is a mock none option');
- expect(widget.fieldValue).toEqual(undefined);
- expect(await dropdown.getValueText()).toEqual('');
+ expect(widget.fieldValue).toEqual({ id: 'empty', name: 'This is a mock none option' });
+ expect(await dropdown.getValueText()).toEqual('This is a mock none option');
});
});
@@ -344,6 +344,22 @@ describe('DropdownCloudWidgetComponent', () => {
});
});
+ it('should NOT display a required error when dropdown is readonly', async () => {
+ widget.field.readOnly = true;
+ fixture.detectChanges();
+ await fixture.whenStable();
+
+ expect(element.querySelector('.adf-invalid')).toBeFalsy();
+
+ const dropdownSelect = element.querySelector('.adf-select');
+ dropdownSelect.dispatchEvent(new Event('blur'));
+
+ fixture.detectChanges();
+ await fixture.whenStable();
+
+ expect(element.querySelector('.adf-invalid')).toBeFalsy();
+ });
+
describe('filter', () => {
beforeEach(() => {
widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id', readOnly: false }), {
@@ -432,7 +448,7 @@ describe('DropdownCloudWidgetComponent', () => {
});
it('should show preselected option for rest options', async () => {
- widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id', readOnly: 'false' }), {
+ widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id', readOnly: false }), {
id: 'dropdown-id',
name: 'date-name',
type: 'dropdown',
@@ -471,7 +487,7 @@ describe('DropdownCloudWidgetComponent', () => {
});
it('should support multiple options for rest options', async () => {
- widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id', readOnly: 'false' }), {
+ widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id', readOnly: false }), {
id: 'dropdown-id',
name: 'date-name',
type: 'dropdown',
diff --git a/lib/process-services-cloud/src/lib/form/components/widgets/dropdown/dropdown-cloud.widget.ts b/lib/process-services-cloud/src/lib/form/components/widgets/dropdown/dropdown-cloud.widget.ts
index 3b852b85ad..ad3d6fa9eb 100644
--- a/lib/process-services-cloud/src/lib/form/components/widgets/dropdown/dropdown-cloud.widget.ts
+++ b/lib/process-services-cloud/src/lib/form/components/widgets/dropdown/dropdown-cloud.widget.ts
@@ -31,7 +31,7 @@ import { BehaviorSubject, combineLatest, Observable, of, Subject } from 'rxjs';
import { filter, map, takeUntil } from 'rxjs/operators';
import { TaskVariableCloud } from '../../../models/task-variable-cloud.model';
-export const DEFAULT_OPTION = {
+export const DEFAULT_OPTION: FormFieldOption = {
id: 'empty',
name: 'Choose one...'
};
@@ -218,16 +218,18 @@ export class DropdownCloudWidgetComponent extends WidgetComponent implements OnI
private buildBodyParam(): any {
const bodyParam = Object.assign({});
if (this.isLinkedWidget()) {
- const parentWidgetValue = this.getParentWidgetValue();
+ const parentWidgetSelectedOption = this.getParentWidgetSelectedOption();
+ const parentWidgetSelectedOptionId = this.field.isEmptyValueOption(parentWidgetSelectedOption) ? null : parentWidgetSelectedOption.id;
+
const parentWidgetId = this.getLinkedWidgetId();
- bodyParam[parentWidgetId] = parentWidgetValue;
+ bodyParam[parentWidgetId] = parentWidgetSelectedOptionId;
}
return bodyParam;
}
private loadFieldOptionsForLinkedWidget() {
- const parentWidgetValue = this.getParentWidgetValue();
- this.parentValueChanged(parentWidgetValue);
+ const parentWidgetSelectedOption = this.getParentWidgetSelectedOption();
+ this.parentValueChanged(parentWidgetSelectedOption);
this.formService.formFieldValueChanged
.pipe(
@@ -240,16 +242,16 @@ export class DropdownCloudWidgetComponent extends WidgetComponent implements OnI
});
}
- private getParentWidgetValue(): string {
+ private getParentWidgetSelectedOption(): FormFieldOption {
const parentWidgetId = this.getLinkedWidgetId();
const parentWidget = this.getFormFieldById(parentWidgetId);
return parentWidget?.value;
}
- private parentValueChanged(value: string) {
- if (value && !this.isNoneValueSelected(value)) {
+ private parentValueChanged(value: FormFieldOption) {
+ if (value && !this.isEmptyValueOption(value)) {
this.isValidRestType() ? this.persistFieldOptionsFromRestApi() : this.persistFieldOptionsFromManualList(value);
- } else if (this.isNoneValueSelected(value)) {
+ } else if (this.isEmptyValueOption(value)) {
this.resetRestApiErrorMessage();
this.resetOptions();
this.resetInvalidValue();
@@ -259,19 +261,23 @@ export class DropdownCloudWidgetComponent extends WidgetComponent implements OnI
}
}
- private isNoneValueSelected(value: string): boolean {
- return value === undefined;
+ private isEmptyValueOptionSelected(): boolean {
+ return this.isEmptyValueOption(this.field.value);
+ }
+
+ private isEmptyValueOption(value: FormFieldOption): boolean {
+ return this.field.isEmptyValueOption(value);
}
private getFormFieldById(fieldId): FormFieldModel {
return this.field.form.getFormFields().filter((field: FormFieldModel) => field.id === fieldId)[0];
}
- private persistFieldOptionsFromManualList(value: string) {
+ private persistFieldOptionsFromManualList(option: FormFieldOption) {
if (this.hasRuleEntries()) {
const rulesEntries = this.field.rule.entries;
rulesEntries.forEach((ruleEntry: RuleEntry) => {
- if (ruleEntry.key === value) {
+ if (ruleEntry.key === option.id) {
this.field.options = ruleEntry.options;
this.resetInvalidValue();
this.field.updateForm();
@@ -287,7 +293,7 @@ export class DropdownCloudWidgetComponent extends WidgetComponent implements OnI
}
private resetValue() {
- this.field.value = '';
+ this.field.value = null;
this.selectionChangedForField(this.field);
this.updateOptions();
this.field.updateForm();
@@ -298,16 +304,15 @@ export class DropdownCloudWidgetComponent extends WidgetComponent implements OnI
}
private isSelectedValueInOptions(): boolean {
- if (Array.isArray(this.fieldValue)) {
- const optionIdList = [...this.field.options].map((option) => option.id);
- const fieldValueIds = this.fieldValue.map((valueOption) => valueOption.id);
- return fieldValueIds.every((valueOptionId) => optionIdList.includes(valueOptionId));
- } else {
- return [...this.field.options].map((option) => option.id).includes(this.fieldValue);
- }
+ const selectedOptions: FormFieldOption[] = Array.isArray(this.fieldValue) ? this.fieldValue : [this.fieldValue];
+
+ return selectedOptions.every((selectedOption) => {
+ const isIncludedInOptions = this.field.options.some((option) => option.id === selectedOption.id);
+ return isIncludedInOptions;
+ });
}
- get fieldValue(): string {
+ get fieldValue(): FormFieldOption {
return this.field.value;
}
@@ -342,40 +347,12 @@ export class DropdownCloudWidgetComponent extends WidgetComponent implements OnI
return this.field?.rule?.ruleOn;
}
- compareDropdownValues(opt1: FormFieldOption | string, opt2: FormFieldOption | string): boolean {
+ compareDropdownValues(opt1: FormFieldOption, opt2: FormFieldOption): boolean {
if (!opt1 || !opt2) {
return false;
}
- if (typeof opt1 === 'string' && typeof opt2 === 'object') {
- return opt1 === opt2.id || opt1 === opt2.name;
- }
-
- if (typeof opt1 === 'object' && typeof opt2 === 'string') {
- return opt1.id === opt2 || opt1.name === opt2;
- }
-
- if (typeof opt1 === 'object' && typeof opt2 === 'object') {
- return opt1.id === opt2.id || opt1.name === opt2.name;
- }
-
- return opt1 === opt2;
- }
-
- getOptionValue(option: FormFieldOption, fieldValue: string): string | FormFieldOption {
- if (this.field.hasMultipleValues) {
- return option;
- }
-
- let optionValue: string = '';
- if (option.id === DEFAULT_OPTION.id) {
- optionValue = undefined;
- } else if (option.name !== fieldValue) {
- optionValue = option.id;
- } else {
- optionValue = option.name;
- }
- return optionValue;
+ return opt1.id === opt2.id && opt1.name === opt2.name;
}
private isValidRestType(): boolean {
@@ -404,11 +381,6 @@ export class DropdownCloudWidgetComponent extends WidgetComponent implements OnI
return this.field.type === 'readonly';
}
- ngOnDestroy() {
- this.onDestroy$.next(true);
- this.onDestroy$.complete();
- }
-
updateOptions(): void {
if (this.isReadOnly()) {
this.list$ = of(this.field.options);
@@ -448,14 +420,22 @@ export class DropdownCloudWidgetComponent extends WidgetComponent implements OnI
showRequiredMessage(): boolean {
return (
- (this.isInvalidFieldRequired() || (this.isNoneValueSelected(this.field.value) && this.isRequired())) &&
+ (this.isInvalidFieldRequired() || (this.isEmptyValueOptionSelected() && this.isRequired())) &&
this.isTouched() &&
!this.isRestApiFailed &&
!this.variableOptionsFailed
);
}
- getDefaultOption(options: FormFieldOption[]): FormFieldOption {
- return options.find((option: FormFieldOption) => option.id === DEFAULT_OPTION.id);
+ getEmptyValueOption(options: FormFieldOption[]): null | FormFieldOption {
+ if (!this.field.hasEmptyValue) {
+ return null;
+ }
+ return options.find((option: FormFieldOption) => this.field.isEmptyValueOption(option));
+ }
+
+ ngOnDestroy() {
+ this.onDestroy$.next(true);
+ this.onDestroy$.complete();
}
}