AAE-22947 Update dropdown-cloud.widget

This commit is contained in:
wiktord2000
2024-06-11 10:21:18 +02:00
parent 1773500d75
commit 727048a013
3 changed files with 66 additions and 70 deletions

View File

@@ -7,8 +7,8 @@
</div>
<div>
<mat-form-field>
<mat-label *ngIf="getDefaultOption(list$ | async) as defaultOption">
{{ defaultOption.name }}
<mat-label *ngIf="getEmptyValueOption(list$ | async) as emptyValueOption">
{{ emptyValueOption.name }}
</mat-label>
<mat-select class="adf-select"
[id]="field.id"
@@ -26,7 +26,7 @@
<adf-select-filter-input *ngIf="showInputFilter" (change)="filter$.next($event)"></adf-select-filter-input>
<mat-option *ngFor="let opt of list$ | async"
[value]="getOptionValue(opt, field.value)"
[value]="opt"
[id]="opt.id">{{opt.name}}
</mat-option>
<mat-option id="readonlyOption" *ngIf="isReadOnlyType()" [value]="field.value">{{field.value}}</mat-option>

View File

@@ -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',

View File

@@ -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();
}
}