AAE-40604 Fix for Dropdown required validation message is not present (#11600)

This commit is contained in:
Darren Thornton
2026-02-03 08:26:45 +00:00
committed by GitHub
parent 84de7c7765
commit 302b3e18ec
3 changed files with 84 additions and 23 deletions
@@ -4,11 +4,13 @@
[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" [style.visibility]="isRequired() ? 'visible' : 'hidden'">*</span>
</label>
</div>
@if(field.leftLabels) {
<div>
<label class="adf-label adf-left-label" [attr.for]="field.id">
{{ field.name | translate }}<span class="adf-asterisk" [style.visibility]="isRequired() ? 'visible' : 'hidden'">*</span>
</label>
</div>
}
<div>
<mat-form-field class="adf-form-field-input">
@if ( (field.name || this.field?.required) && !field.leftLabels) {
@@ -27,7 +29,9 @@
#select
(keydown.escape)="select.close()"
>
<adf-select-filter-input *ngIf="showInputFilter" (change)="filter$.next($event)" />
@if(showInputFilter) {
<adf-select-filter-input (change)="filter$.next($event)" />
}
@for(opt of (list$ | async); track opt.id) {
<mat-option [value]="opt" [id]="opt.id">
@@ -48,19 +52,23 @@
<div
class="adf-error-messages-container"
[ngClass]="!previewState && !field.readOnly ? 'adf-error-messages-container-visible' : 'adf-error-messages-container-hidden'"
[ngClass]="!field.readOnly ? 'adf-error-messages-container-visible' : 'adf-error-messages-container-hidden'"
>
<error-widget class="adf-dropdown-required-message" *ngIf="showRequiredMessage" required="{{ 'FORM.FIELD.REQUIRED' | translate }}" />
<error-widget
class="adf-dropdown-failed-message"
*ngIf="isRestApiFailed"
required="{{ 'FORM.FIELD.REST_API_FAILED' | translate: { hostname: restApiHostName } }}"
/>
<error-widget
class="adf-dropdown-failed-message"
*ngIf="variableOptionsFailed"
required="{{ 'FORM.FIELD.VARIABLE_DROPDOWN_OPTIONS_FAILED' | translate }}"
/>
@if(showRequiredMessage) {
<error-widget class="adf-dropdown-required-message" required="{{ 'FORM.FIELD.REQUIRED' | translate }}" />
}
@if(!previewState && isRestApiFailed) {
<error-widget
class="adf-dropdown-failed-message"
required="{{ 'FORM.FIELD.REST_API_FAILED' | translate: { hostname: restApiHostName } }}"
/>
}
@if(!previewState && variableOptionsFailed) {
<error-widget
class="adf-dropdown-failed-message"
required="{{ 'FORM.FIELD.VARIABLE_DROPDOWN_OPTIONS_FAILED' | translate }}"
/>
}
</div>
</div>
</div>
@@ -253,6 +253,24 @@ describe('DropdownCloudWidgetComponent', () => {
expect(widget.isRestApiFailed).toBe(true);
expect(widget.field.options.length).toEqual(0);
expect(errorMessageElement.nativeElement.textContent.trim()).toBe(errorIcon + 'FORM.FIELD.REST_API_FAILED');
const errorsMessagesElement = fixture.debugElement.query(By.css('.adf-error-messages-container'));
expect(errorsMessagesElement.nativeElement.classList.contains('adf-error-messages-container-visible')).toBe(true);
});
it('should NOT show required message when REST API failed', () => {
widget.field.readOnly = false;
widget.field.required = true;
widget.ngOnInit();
widget.dropdownControl.markAsTouched();
fixture.detectChanges();
expect(widget.isRestApiFailed).toBe(true);
const requiredErrorElement = fixture.debugElement.query(By.css('.adf-dropdown-required-message .adf-error-text'));
expect(requiredErrorElement).toBeFalsy();
const restApiFailedElement = getErrorMessageElement();
expect(restApiFailedElement).toBeTruthy();
});
it('should NOT show error message when widget is readonly', async () => {
@@ -268,6 +286,21 @@ describe('DropdownCloudWidgetComponent', () => {
const errorsMessagesElement = fixture.debugElement.query(By.css('.adf-error-messages-container'));
expect(errorsMessagesElement.nativeElement.classList.contains('adf-error-messages-container-hidden')).toBe(true);
});
it('should NOT show REST API failed error message when form is in preview state', () => {
widget.field.readOnly = false;
spyOn(formCloudService, 'getPreviewState').and.returnValue(true);
widget.ngOnInit();
fixture.detectChanges();
expect(getRestWidgetDataSpy).toHaveBeenCalled();
expect(widget.isRestApiFailed).toBe(true);
expect(widget.field.options.length).toEqual(0);
const failedErrorMsgElement = getErrorMessageElement();
expect(failedErrorMsgElement).toBeNull();
});
});
it('should preselect dropdown widget value when Json (rest call) passed', async () => {
@@ -405,6 +438,9 @@ describe('DropdownCloudWidgetComponent', () => {
expect(element.querySelector('.adf-invalid')).toBeTruthy();
const errorsMessagesElement = fixture.debugElement.query(By.css('.adf-error-messages-container'));
expect(errorsMessagesElement.nativeElement.classList.contains('adf-error-messages-container-visible')).toBe(true);
const requiredErrorElement = fixture.debugElement.query(By.css('.adf-dropdown-required-message .adf-error-text'));
expect(requiredErrorElement.nativeElement.innerText).toEqual('FORM.FIELD.REQUIRED');
});
@@ -1158,6 +1194,24 @@ describe('DropdownCloudWidgetComponent', () => {
checkDropdownVariableOptionsFailed();
});
it('should NOT show required message when variable options failed', () => {
widget.field = getVariableDropdownWidget(
'variables.json-variable',
'response.wrongPath.players',
'playerId',
'playerFullName',
mockProcessVariablesWithJson
);
widget.field.required = true;
fixture.detectChanges();
expect(widget.variableOptionsFailed).toBe(true);
const requiredErrorElement = fixture.debugElement.query(By.css('.adf-dropdown-required-message .adf-error-text'));
expect(requiredErrorElement).toBeFalsy();
const variableFailedElement = fixture.debugElement.query(By.css('.adf-dropdown-failed-message'));
expect(variableFailedElement).toBeTruthy();
});
it('should return empty array and display error when id is incorrect', () => {
widget.field = getVariableDropdownWidget(
'variables.json-variable',
@@ -1204,7 +1258,7 @@ describe('DropdownCloudWidgetComponent', () => {
checkDropdownVariableOptionsFailed();
});
it('should NOT display errors if form is in the preview state', () => {
it('should NOT display variable options failed error when form is in the preview state', () => {
widget.field = getVariableDropdownWidget(
'variables.json-variable',
'response.wrongPath.players',
@@ -1215,8 +1269,8 @@ describe('DropdownCloudWidgetComponent', () => {
spyOn(formCloudService, 'getPreviewState').and.returnValue(true);
fixture.detectChanges();
const errorsMessagesElement = fixture.debugElement.query(By.css('.adf-error-messages-container'));
expect(errorsMessagesElement.nativeElement.classList.contains('adf-error-messages-container-hidden')).toBe(true);
const failedErrorMsgElement = fixture.debugElement.query(By.css('.adf-dropdown-failed-message'));
expect(failedErrorMsgElement).toBeNull();
});
it('should NOT display errors if field is readonly', () => {
@@ -29,7 +29,7 @@ import {
SelectFilterInputComponent,
WidgetComponent
} from '@alfresco/adf-core';
import { AsyncPipe, NgClass, NgIf } from '@angular/common';
import { AsyncPipe, NgClass } from '@angular/common';
import { Component, DestroyRef, inject, OnInit, ViewEncapsulation } from '@angular/core';
import { FormControl, ReactiveFormsModule, Validators } from '@angular/forms';
import { MatFormFieldModule } from '@angular/material/form-field';
@@ -61,7 +61,6 @@ export const DROPDOWN_CLOUD_WIDGET_SET_VALUE_DEBOUNCE = 100;
},
encapsulation: ViewEncapsulation.None,
imports: [
NgIf,
NgClass,
AsyncPipe,
ReactiveFormsModule,