Skip to content

Commit

Permalink
Revert "AAE-23521 Fix improve dropdown reactive form (#10040)"
Browse files Browse the repository at this point in the history
This reverts commit f88ff10.
  • Loading branch information
VitoAlbano committed Aug 9, 2024
1 parent 80a70cf commit 2a60f73
Show file tree
Hide file tree
Showing 13 changed files with 321 additions and 456 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ export class FormFieldTypes {

static VALIDATABLE_TYPES: string[] = [FormFieldTypes.DISPLAY_EXTERNAL_PROPERTY];

static REACTIVE_TYPES: string[] = [FormFieldTypes.DATE, FormFieldTypes.DATETIME, FormFieldTypes.DROPDOWN];
static REACTIVE_TYPES: string[] = [FormFieldTypes.DATE, FormFieldTypes.DATETIME];

static CONSTANT_VALUE_TYPES: string[] = [FormFieldTypes.DISPLAY_EXTERNAL_PROPERTY];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,51 @@ describe('FormFieldValidator', () => {
expect(validator.validate(field)).toBe(true);
});

it('should fail (display error) for multiple type dropdown with zero selection', () => {
const field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.DROPDOWN,
value: [{ id: 'id_cat', name: 'Cat' }],
required: true,
selectionType: 'multiple',
hasEmptyValue: false,
options: [
{ id: 'id_cat', name: 'Cat' },
{ id: 'id_dog', name: 'Dog' }
]
});

const validateBeforeUnselect = validator.validate(field);
field.value = [];
const validateAfterUnselect = validator.validate(field);

expect(validateBeforeUnselect).toBe(true);
expect(validateAfterUnselect).toBe(false);
});

it('should fail (display error) for dropdown with null value', () => {
const field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.DROPDOWN,
value: null,
required: true,
options: [{ id: 'one', name: 'one' }],
selectionType: 'multiple'
});

expect(validator.validate(field)).toBe(false);
});

it('should fail (display error) for dropdown with empty object', () => {
const field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.DROPDOWN,
value: {},
required: true,
options: [{ id: 'one', name: 'one' }],
selectionType: 'multiple'
});

expect(validator.validate(field)).toBe(false);
});

it('should fail (display error) for radio buttons', () => {
const field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.RADIO_BUTTONS,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export class RequiredFieldValidator implements FormFieldValidator {
FormFieldTypes.NUMBER,
FormFieldTypes.BOOLEAN,
FormFieldTypes.TYPEAHEAD,
FormFieldTypes.DROPDOWN,
FormFieldTypes.PEOPLE,
FormFieldTypes.FUNCTIONAL_GROUP,
FormFieldTypes.RADIO_BUTTONS,
Expand All @@ -50,6 +51,22 @@ export class RequiredFieldValidator implements FormFieldValidator {

validate(field: FormFieldModel): boolean {
if (this.isSupported(field) && field.isVisible) {
if (field.type === FormFieldTypes.DROPDOWN) {
if (field.hasMultipleValues) {
return Array.isArray(field.value) && !!field.value.length;
}

if (field.hasEmptyValue && field.emptyOption) {
if (field.value === field.emptyOption.id) {
return false;
}
}

if (field.required && field.value && typeof field.value === 'object' && !Object.keys(field.value).length) {
return false;
}
}

if (field.type === FormFieldTypes.RADIO_BUTTONS) {
const option = field.options.find((opt) => opt.id === field.value);
return !!option;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
.adf-error {
display: flex;
align-items: center;

&-widget-container {
height: auto;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,50 +1,43 @@
<div
class="adf-dropdown-widget {{field.className}}"
[class.adf-invalid]="dropdownControl.invalid && dropdownControl.touched"
[class.adf-readonly]="field.readOnly"
[class.adf-left-label-input-container]="field.leftLabels"
>
<div *ngIf="field.leftLabels">
<label class="adf-label adf-left-label" [attr.for]="field.id">
{{ field.name | translate }}<span class="adf-asterisk" *ngIf="isRequired()">*</span>
<div class="adf-dropdown-widget {{field.className}}"
[class.adf-invalid]="(!field.isValid && isTouched()) || isRestApiFailed" [class.adf-readonly]="field.readOnly" [class.adf-left-label-input-container]="field.leftLabels">
<div class="adf-dropdown-widget-top-labels">
<label class="adf-label" [attr.for]="field.id" [class.adf-left-label]="field.leftLabels">{{field.name | translate }}<span class="adf-asterisk"
*ngIf="isRequired()">*</span>
</label>
</div>
<div>
<mat-form-field>
<label *ngIf="!field.leftLabels" class="adf-label" [attr.for]="field.id">
{{ field.name | translate }}<span class="adf-asterisk" *ngIf="isRequired()">*</span>
</label>
<mat-select
class="adf-select"
[formControl]="dropdownControl"
[id]="field.id"
[compareWith]="compareDropdownValues"
[title]="field.tooltip"
panelClass="adf-select-filter"
[multiple]="field.hasMultipleValues"
>
<mat-label *ngIf="getDefaultOption(list$ | async) as defaultOption">
{{ defaultOption.name }}
</mat-label>
<mat-select class="adf-select"
[id]="field.id"
[(ngModel)]="field.value"
[disabled]="field.readOnly"
[compareWith]="compareDropdownValues"
(ngModelChange)="selectionChangedForField(field)"
[title]="field.tooltip"
[required]="isRequired()"
panelClass="adf-select-filter"
(blur)="markAsTouched()"
[multiple]="field.hasMultipleValues">
<adf-select-filter-input *ngIf="showInputFilter" (change)="filter$.next($event)"></adf-select-filter-input>

<mat-option *ngFor="let opt of list$ | async" [value]="opt" [id]="opt.id">{{opt.name}}</mat-option>
<mat-option id="readonlyOption" *ngIf="isReadOnlyType" [value]="field.value">{{field.value}}</mat-option>
<mat-option *ngFor="let opt of list$ | async"
[value]="getOptionValue(opt, field.value)"
[id]="opt.id">{{opt.name}}
</mat-option>
<mat-option id="readonlyOption" *ngIf="isReadOnlyType()" [value]="field.value">{{field.value}}</mat-option>
</mat-select>
</mat-form-field>
<div *ngIf="!previewState && !field.readOnly">
<error-widget
class="adf-dropdown-required-message"
*ngIf="showRequiredMessage"
required="{{ 'FORM.FIELD.REQUIRED' | translate }}"
></error-widget>
<error-widget
class="adf-dropdown-failed-message"
*ngIf="isRestApiFailed"
required="{{ 'FORM.FIELD.REST_API_FAILED' | translate: { hostname: restApiHostName } }}"
></error-widget>
<error-widget
class="adf-dropdown-failed-message"
*ngIf="variableOptionsFailed"
required="{{ 'FORM.FIELD.VARIABLE_DROPDOWN_OPTIONS_FAILED' | translate }}"
></error-widget>
<div *ngIf="!previewState && !isReadOnlyField">
<error-widget [error]="field.validationSummary"></error-widget>
<error-widget class="adf-dropdown-required-message" *ngIf="showRequiredMessage()"
required="{{ 'FORM.FIELD.REQUIRED' | translate }}"></error-widget>
<error-widget class="adf-dropdown-failed-message" *ngIf="isRestApiFailed"
required="{{ 'FORM.FIELD.REST_API_FAILED' | translate: { hostname: restApiHostName } }}"></error-widget>
<error-widget class="adf-dropdown-failed-message" *ngIf="variableOptionsFailed"
required="{{ 'FORM.FIELD.VARIABLE_DROPDOWN_OPTIONS_FAILED' | translate }}"></error-widget>
</div>
</div>
</div>
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
@import 'styles/mat-selectors';

.adf {
&-dropdown-widget {
width: 100%;
Expand All @@ -26,9 +24,5 @@
&-dropdown-failed-message .adf-error-container {
margin-top: 1px;
}

#{$mat-select-arrow-wrapper} {
height: auto;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import { TaskVariableCloud } from '../../../models/task-variable-cloud.model';
import { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { MatSelectHarness } from '@angular/material/select/testing';
import { MatFormFieldHarness } from '@angular/material/form-field/testing';
import { DebugElement } from '@angular/core';

describe('DropdownCloudWidgetComponent', () => {
Expand Down Expand Up @@ -94,15 +95,15 @@ describe('DropdownCloudWidgetComponent', () => {
it('should select the default value when an option is chosen as default', async () => {
widget.field.value = 'option_2';

expect(widget.field.value).toEqual('option_2');
expect(widget.fieldValue).toEqual('option_2');
});

it('should select the empty value when no default is chosen', async () => {
widget.field.value = 'empty';
const dropdown = await loader.getHarness(MatSelectHarness.with({ selector: '.adf-select' }));
await dropdown.open();

expect(widget.field.value).toEqual('empty');
expect(widget.fieldValue).toEqual('empty');
});

it('should load data from restUrl and populate options', async () => {
Expand Down Expand Up @@ -294,14 +295,17 @@ describe('DropdownCloudWidgetComponent', () => {
await dropdown.clickOptions({ selector: '[id="opt_1"]' });

expect(await dropdown.getValueText()).toEqual('option_1');
expect(widget.field.value).toEqual('opt_1');
expect(widget.fieldValue).toEqual('opt_1');

await dropdown.open();
await dropdown.clickOptions({ selector: '[id="empty"]' });

expect(widget.field.value).toEqual(undefined);
const formField = await loader.getHarness(MatFormFieldHarness);
const dropdownLabel = await formField.getLabel();

expect(await dropdown.getValueText()).toEqual('This is a mock none option');
expect(dropdownLabel).toEqual('This is a mock none option');
expect(widget.fieldValue).toEqual(undefined);
expect(await dropdown.getValueText()).toEqual('');
});
});

Expand Down Expand Up @@ -524,58 +528,6 @@ describe('DropdownCloudWidgetComponent', () => {
{ id: 'opt_4', name: 'option_4' }
]);
});

it('should fail (display error) for multiple type dropdown with zero selection', async () => {
widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id', readOnly: 'false' }), {
type: FormFieldTypes.DROPDOWN,
value: [{ id: 'id_cat', name: 'Cat' }],
required: true,
selectionType: 'multiple',
hasEmptyValue: false,
options: [
{ id: 'id_cat', name: 'Cat' },
{ id: 'id_dog', name: 'Dog' }
]
});

const validateBeforeUnselect = widget.dropdownControl.valid;

const dropdown = await loader.getHarness(MatSelectHarness.with({ selector: '.adf-select' }));
await dropdown.clickOptions({ selector: '[id="id_cat"]' });

const validateAfterUnselect = widget.dropdownControl.valid;

expect(validateBeforeUnselect).toBe(true);
expect(validateAfterUnselect).toBe(false);
});

it('should fail (display error) for dropdown with null value', () => {
widget.field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.DROPDOWN,
value: null,
required: true,
options: [{ id: 'one', name: 'one' }],
selectionType: 'multiple'
});

widget.ngOnInit();

expect(widget.dropdownControl.valid).toBe(false);
});

it('should fail (display error) for dropdown with empty object', () => {
widget.field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.DROPDOWN,
value: {},
required: true,
options: [{ id: 'one', name: 'one' }],
selectionType: 'multiple'
});

widget.ngOnInit();

expect(widget.dropdownControl.valid).toBe(false);
});
});

describe('Linked Dropdown', () => {
Expand Down Expand Up @@ -745,7 +697,7 @@ describe('DropdownCloudWidgetComponent', () => {
fixture.detectChanges();

expect(widget.field.options).toEqual(mockConditionalEntries[0].options);
expect(widget.field.value).toEqual('');
expect(widget.fieldValue).toEqual('');
});

it('should not reset the current value when it is part of the available options', () => {
Expand All @@ -758,7 +710,7 @@ describe('DropdownCloudWidgetComponent', () => {
fixture.detectChanges();

expect(widget.field.options).toEqual(mockConditionalEntries[0].options);
expect(widget.field.value).toEqual('ATH');
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)', () => {
Expand Down
Loading

0 comments on commit 2a60f73

Please sign in to comment.