AAE-43974 error widget replaced with mat-error

This commit is contained in:
Anamika Dey
2026-05-20 14:19:32 +05:30
parent 15d63b6fe9
commit 81bfad04e9
15 changed files with 181 additions and 67 deletions
@@ -15,15 +15,16 @@
adf-auto-focus
/>
<mat-hint *ngIf="form.controls['name'].dirty">
<span *ngIf="form.controls['name'].errors?.required">
@if (form.controls['name'].errors?.required) {
<mat-error>
{{ 'CORE.FOLDER_DIALOG.FOLDER_NAME.ERRORS.REQUIRED' | translate }}
</span>
<span *ngIf="!form.controls['name'].errors?.required && form.controls['name'].errors?.message">
</mat-error>
}
@if (!form.controls['name'].errors?.required && form.controls['name'].errors?.message) {
<mat-error>
{{ form.controls['name'].errors?.message | translate }}
</span>
</mat-hint>
</mat-error>
}
</mat-form-field>
<mat-form-field class="adf-full-width adf-folder-dialog-form-field">
@@ -40,6 +40,7 @@
.adf-container-widget {
.adf-grid-list {
display: grid;
row-gap: 16px;
&-column-view {
display: flex;
@@ -65,6 +66,7 @@
display: flex;
flex-direction: column;
flex: 1 1 auto;
gap: 16px;
}
&-item {
@@ -10,7 +10,7 @@
>
</div>
<div class="adf-amount-widget-container">
<mat-form-field class="adf-amount-widget__input adf-form-field-input" [floatLabel]="placeholder ? 'always' : null" subscriptSizing="fixed">
<mat-form-field class="adf-amount-widget__input adf-form-field-input" [floatLabel]="placeholder ? 'always' : null" subscriptSizing="dynamic">
@if ( (field.name || field?.required) && !field.leftLabels) { <mat-label class="adf-label" [attr.for]="field.id">{{field.name | translate }}</mat-label> }
@if(!enableDisplayBasedOnLocale) {
<span matTextPrefix class="adf-amount-widget__prefix-spacing">{{ currency }}&nbsp;</span>
@@ -10,7 +10,8 @@
<div class="adf-date-time-widget-container">
<mat-form-field class="adf-date-time-widget adf-form-field-input"
[class.adf-left-label-input-datepicker]="field.leftLabels"
[floatLabel]="field.placeholder ? 'always' : null">
[floatLabel]="field.placeholder ? 'always' : null"
subscriptSizing="dynamic">
@if( (field.name || field?.required) && !field.leftLabels) {
<mat-label class="adf-label" [attr.for]="field.id">
{{ field.name | translate }} ({{ field.dateDisplayFormat }})
@@ -36,9 +37,11 @@
[touchUi]="true"
[timeInterval]="5"
[disabled]="field.readOnly" />
@if (datetimeInputControl.invalid && datetimeInputControl.touched && field.validationSummary?.message) {
<mat-error>
{{ field.validationSummary.message | translate:translateParameters }}
</mat-error>
}
</mat-form-field>
<div class="adf-error-messages-container">
<error-widget *ngIf="datetimeInputControl.invalid && datetimeInputControl.touched" [error]="field.validationSummary" />
</div>
</div>
</div>
@@ -27,7 +27,6 @@ import { DatetimeAdapter, MAT_DATETIME_FORMATS, MatDatetimepickerModule } from '
import { TranslatePipe } from '@ngx-translate/core';
import { ADF_DATE_FORMATS, ADF_DATETIME_FORMATS, AdfDateFnsAdapter, AdfDateTimeFnsAdapter, DateFnsUtils } from '../../../../common';
import { FormService } from '../../../services/form.service';
import { ErrorWidgetComponent } from '../error/error.component';
import { WidgetComponent } from '../widget.component';
import { ErrorMessageModel } from '../core/error-message.model';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
@@ -46,13 +45,14 @@ import { ReactiveFormWidget } from '../reactive-widget.interface';
host: {
'(click)': 'event($event)'
},
imports: [NgIf, TranslatePipe, MatFormFieldModule, MatInputModule, MatDatetimepickerModule, ReactiveFormsModule, ErrorWidgetComponent],
imports: [NgIf, TranslatePipe, MatFormFieldModule, MatInputModule, MatDatetimepickerModule, ReactiveFormsModule],
encapsulation: ViewEncapsulation.None
})
export class DateTimeWidgetComponent extends WidgetComponent implements OnInit, ReactiveFormWidget {
minDate: Date;
maxDate: Date;
datetimeInputControl: FormControl<Date> = new FormControl<Date>(null);
translateParameters: Record<string, string> = {};
public readonly formService = inject(FormService);
private readonly destroyRef = inject(DestroyRef);
@@ -116,6 +116,15 @@ export class DateTimeWidgetComponent extends WidgetComponent implements OnInit,
this.resetErrors();
this.field.markAsValid();
}
this.updateTranslateParameters();
}
private updateTranslateParameters(): void {
if (this.field.validationSummary?.isActive()) {
this.translateParameters = this.field.validationSummary.getAttributesAsJsonObj();
} else {
this.translateParameters = {};
}
}
private handleErrors(errors: ValidationErrors): void {
@@ -1,5 +1,5 @@
<div class="{{ field.className }} date-widget-container" id="data-widget" [class.adf-invalid]="dateInputControl.invalid && dateInputControl.touched">
<mat-form-field class="adf-date-widget adf-form-field-input" [floatLabel]="field.placeholder ? 'always' : null">
<mat-form-field class="adf-date-widget adf-form-field-input" [floatLabel]="field.placeholder ? 'always' : null" subscriptSizing="dynamic">
<mat-label class="adf-label"
[id]="field.id + '-label'"
[attr.for]="field.id">
@@ -19,11 +19,10 @@
<mat-datepicker #datePicker
[startAt]="startAt"
[disabled]="field.readOnly" />
@if (dateInputControl.invalid && dateInputControl.touched && field.validationSummary?.message) {
<mat-error>
{{ field.validationSummary.message | translate:translateParameters }}
</mat-error>
}
</mat-form-field>
<div class="adf-error-messages-container">
<error-widget
*ngIf="dateInputControl.invalid && dateInputControl.touched"
[error]="field.validationSummary"
/>
</div>
</div>
@@ -17,7 +17,6 @@
/* eslint-disable @angular-eslint/component-selector */
import { NgIf } from '@angular/common';
import { Component, DestroyRef, inject, OnInit, ViewEncapsulation } from '@angular/core';
import { FormControl, ReactiveFormsModule, ValidationErrors, Validators } from '@angular/forms';
import { DateAdapter, MAT_DATE_FORMATS } from '@angular/material/core';
@@ -27,7 +26,6 @@ import { MatInputModule } from '@angular/material/input';
import { TranslatePipe } from '@ngx-translate/core';
import { ADF_DATE_FORMATS, AdfDateFnsAdapter, DateFnsUtils, DEFAULT_DATE_FORMAT } from '../../../../common';
import { FormService } from '../../../services/form.service';
import { ErrorWidgetComponent } from '../error/error.component';
import { WidgetComponent } from '../widget.component';
import { ErrorMessageModel } from '../core/error-message.model';
import { parseISO } from 'date-fns';
@@ -53,13 +51,14 @@ import { ReactiveFormWidget } from '../reactive-widget.interface';
'(invalid)': 'event($event)',
'(select)': 'event($event)'
},
imports: [MatFormFieldModule, TranslatePipe, MatInputModule, MatDatepickerModule, ReactiveFormsModule, ErrorWidgetComponent, NgIf],
imports: [MatFormFieldModule, TranslatePipe, MatInputModule, MatDatepickerModule, ReactiveFormsModule],
encapsulation: ViewEncapsulation.None
})
export class DateWidgetComponent extends WidgetComponent implements OnInit, ReactiveFormWidget {
minDate: Date;
maxDate: Date;
startAt: Date;
translateParameters: Record<string, string> = {};
dateInputControl: FormControl<Date> = new FormControl<Date>(null);
@@ -126,6 +125,15 @@ export class DateWidgetComponent extends WidgetComponent implements OnInit, Reac
this.resetErrors();
this.field.markAsValid();
}
this.updateTranslateParameters();
}
private updateTranslateParameters(): void {
if (this.field.validationSummary?.isActive()) {
this.translateParameters = this.field.validationSummary.getAttributesAsJsonObj();
} else {
this.translateParameters = {};
}
}
private handleErrors(errors: ValidationErrors): void {
@@ -9,7 +9,7 @@
</div>
<div class="adf-decimal-widget-container">
<mat-form-field class="adf-form-field-input" [floatLabel]="field.placeholder ? 'always' : null">
<mat-form-field class="adf-form-field-input" [floatLabel]="field.placeholder ? 'always' : null" subscriptSizing="dynamic">
@if ( (field.name || field?.required) && !field.leftLabels) { <mat-label class="adf-label" [attr.for]="field.id">{{ field.name | translate }}</mat-label> }
<input matInput
class="adf-input"
@@ -22,15 +22,18 @@
[disabled]="field.readOnly"
[placeholder]="field.placeholder"
[title]="field.tooltip"
(blur)="markAsTouched()" />
[errorStateMatcher]="errorStateMatcher"
(blur)="onBlur()" />
@if (field.validationSummary?.message) {
<mat-error>
{{ field.validationSummary.message | translate:translateParameters }}
</mat-error>
}
@if (isInvalidFieldRequired() && isTouched()) {
<mat-error>
{{ 'FORM.FIELD.REQUIRED' | translate }}
</mat-error>
}
</mat-form-field>
<div class="adf-error-messages-container">
<error-widget [error]="field.validationSummary" />
<error-widget
*ngIf="isInvalidFieldRequired() && isTouched()"
required="{{ 'FORM.FIELD.REQUIRED' | translate }}"
/>
</div>
</div>
</div>
@@ -16,12 +16,12 @@
*/
import { NgIf } from '@angular/common';
import { Component, ViewEncapsulation } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { Component, OnInit, ViewEncapsulation } from '@angular/core';
import { FormsModule, FormGroupDirective, NgForm, UntypedFormControl } from '@angular/forms';
import { ErrorStateMatcher } from '@angular/material/core';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { TranslatePipe } from '@ngx-translate/core';
import { ErrorWidgetComponent } from '../error/error.component';
import { WidgetComponent } from '../widget.component';
@Component({
@@ -39,7 +39,34 @@ import { WidgetComponent } from '../widget.component';
'(invalid)': 'event($event)',
'(select)': 'event($event)'
},
imports: [NgIf, TranslatePipe, MatFormFieldModule, MatInputModule, FormsModule, ErrorWidgetComponent],
imports: [NgIf, TranslatePipe, MatFormFieldModule, MatInputModule, FormsModule],
encapsulation: ViewEncapsulation.None
})
export class DecimalWidgetComponent extends WidgetComponent {}
export class DecimalWidgetComponent extends WidgetComponent implements OnInit {
errorStateMatcher: ErrorStateMatcher;
translateParameters: Record<string, string> = {};
ngOnInit(): void {
this.initErrorStateMatcher();
}
private initErrorStateMatcher(): void {
this.errorStateMatcher = {
isErrorState: (_control: UntypedFormControl | null, _form: FormGroupDirective | NgForm | null): boolean =>
!this.field.isValid && this.isTouched()
};
}
private updateTranslateParameters(): void {
if (this.field.validationSummary?.isActive()) {
this.translateParameters = this.field.validationSummary.getAttributesAsJsonObj();
} else {
this.translateParameters = {};
}
}
onBlur(): void {
this.markAsTouched();
this.updateTranslateParameters();
}
}
@@ -24,19 +24,26 @@
[disabled]="field.readOnly || readOnly"
[placeholder]="field.placeholder"
[title]="field.tooltip"
(blur)="markAsTouched()"
[errorStateMatcher]="errorStateMatcher"
(blur)="onBlur()"
>
</textarea>
</mat-form-field>
<div *ngIf="field.maxLength > 0" class="adf-multiline-word-counter">
<span class="adf-multiline-word-counter-value">{{ field?.value?.length || 0 }}/{{ field.maxLength }}</span>
</div>
<div class="adf-error-messages-container">
<error-widget [error]="field.validationSummary" />
<error-widget
*ngIf="isInvalidFieldRequired() && isTouched()"
class="adf-multiline-required-message"
required="{{ 'FORM.FIELD.REQUIRED' | translate }}"
/>
@if (field.maxLength > 0) {
<div class="adf-multiline-word-counter">
<span class="adf-multiline-word-counter-value">{{ field?.value?.length || 0 }}/{{ field.maxLength }}</span>
</div>
}
<div class="adf-multiline-error-container">
@if (field.validationSummary?.message) {
<mat-error>
{{ field.validationSummary.message | translate:translateParameters }}
</mat-error>
}
@if (isInvalidFieldRequired() && isTouched()) {
<mat-error>
{{ 'FORM.FIELD.REQUIRED' | translate }}
</mat-error>
}
</div>
</div>
@@ -26,6 +26,11 @@
padding-left: 0;
}
&-multiline-error-container {
width: 100%;
font-size: var(--mat-sys-body-small-size);
}
&-multiline-required-message {
display: flex;
}
@@ -17,16 +17,15 @@
/* eslint-disable @angular-eslint/component-selector */
import { NgIf } from '@angular/common';
import { Component, DestroyRef, inject, OnInit, ViewEncapsulation } from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { FormsModule } from '@angular/forms';
import { FormsModule, FormGroupDirective, NgForm, UntypedFormControl } from '@angular/forms';
import { ErrorStateMatcher } from '@angular/material/core';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { TranslatePipe } from '@ngx-translate/core';
import { isObservable } from 'rxjs';
import { ADF_CUSTOM_MESSAGE } from '../core/custom-validation-message.token';
import { ErrorWidgetComponent } from '../error/error.component';
import { WidgetComponent } from '../widget.component';
@Component({
@@ -44,14 +43,18 @@ import { WidgetComponent } from '../widget.component';
'(invalid)': 'event($event)',
'(select)': 'event($event)'
},
imports: [MatFormFieldModule, NgIf, TranslatePipe, MatInputModule, FormsModule, ErrorWidgetComponent],
imports: [MatFormFieldModule, TranslatePipe, MatInputModule, FormsModule],
encapsulation: ViewEncapsulation.None
})
export class MultilineTextWidgetComponentComponent extends WidgetComponent implements OnInit {
private readonly destroyRef = inject(DestroyRef);
private readonly enableCustomMessage = inject(ADF_CUSTOM_MESSAGE, { optional: true });
errorStateMatcher: ErrorStateMatcher;
translateParameters: Record<string, string> = {};
ngOnInit(): void {
this.initErrorStateMatcher();
if (this.enableCustomMessage != null) {
if (isObservable(this.enableCustomMessage)) {
this.enableCustomMessage.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((enabled: boolean) => {
@@ -66,4 +69,24 @@ export class MultilineTextWidgetComponentComponent extends WidgetComponent imple
this.field.enableCustomValidationMessage = false;
}
}
private initErrorStateMatcher(): void {
this.errorStateMatcher = {
isErrorState: (_control: UntypedFormControl | null, _form: FormGroupDirective | NgForm | null): boolean =>
!this.field.isValid && this.isTouched()
};
}
private updateTranslateParameters(): void {
if (this.field.validationSummary?.isActive()) {
this.translateParameters = this.field.validationSummary.getAttributesAsJsonObj();
} else {
this.translateParameters = {};
}
}
onBlur(): void {
this.markAsTouched();
this.updateTranslateParameters();
}
}
@@ -9,7 +9,7 @@
</label>
</div>
<div class="adf-number-widget-container">
<mat-form-field class="adf-form-field-input" [floatLabel]="field.placeholder ? 'always' : null">
<mat-form-field class="adf-form-field-input" [floatLabel]="field.placeholder ? 'always' : null" subscriptSizing="dynamic">
@if( (field.name || this.field?.required) && !field.leftLabels) {
<mat-label class="adf-label" [attr.for]="field.id">
{{ field.name | translate }}
@@ -27,14 +27,18 @@
[disabled]="field.readOnly"
[placeholder]="field.placeholder"
[title]="field.tooltip"
(blur)="markAsTouched()">
[errorStateMatcher]="errorStateMatcher"
(blur)="onBlur()">
@if (field.validationSummary?.message) {
<mat-error>
{{ field.validationSummary.message | translate:translateParameters }}
</mat-error>
}
@if (isInvalidFieldRequired() && isTouched()) {
<mat-error>
{{ 'FORM.FIELD.REQUIRED' | translate }}
</mat-error>
}
</mat-form-field>
<div class="adf-error-messages-container">
<error-widget [error]="field.validationSummary" />
<error-widget
*ngIf="isInvalidFieldRequired() && isTouched()"
required="{{ 'FORM.FIELD.REQUIRED' | translate }}"
/>
</div>
</div>
</div>
@@ -19,12 +19,12 @@
import { NgIf } from '@angular/common';
import { Component, inject, OnInit, ViewEncapsulation } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { FormsModule, FormGroupDirective, NgForm, UntypedFormControl } from '@angular/forms';
import { ErrorStateMatcher } from '@angular/material/core';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { TranslatePipe } from '@ngx-translate/core';
import { DecimalNumberPipe } from '../../../../pipes';
import { ErrorWidgetComponent } from '../error/error.component';
import { WidgetComponent } from '../widget.component';
@Component({
@@ -42,12 +42,14 @@ import { WidgetComponent } from '../widget.component';
'(invalid)': 'event($event)',
'(select)': 'event($event)'
},
imports: [NgIf, TranslatePipe, MatFormFieldModule, MatInputModule, FormsModule, ErrorWidgetComponent],
imports: [NgIf, TranslatePipe, MatFormFieldModule, MatInputModule, FormsModule],
providers: [DecimalNumberPipe],
encapsulation: ViewEncapsulation.None
})
export class NumberWidgetComponent extends WidgetComponent implements OnInit {
displayValue: number;
errorStateMatcher: ErrorStateMatcher;
translateParameters: Record<string, string> = {};
private readonly decimalNumberPipe = inject(DecimalNumberPipe);
@@ -57,6 +59,27 @@ export class NumberWidgetComponent extends WidgetComponent implements OnInit {
} else {
this.displayValue = this.field.value;
}
this.initErrorStateMatcher();
}
private initErrorStateMatcher(): void {
this.errorStateMatcher = {
isErrorState: (_control: UntypedFormControl | null, _form: FormGroupDirective | NgForm | null): boolean =>
!this.field.isValid && this.isTouched()
};
}
private updateTranslateParameters(): void {
if (this.field.validationSummary?.isActive()) {
this.translateParameters = this.field.validationSummary.getAttributesAsJsonObj();
} else {
this.translateParameters = {};
}
}
onBlur(): void {
this.markAsTouched();
this.updateTranslateParameters();
}
protected onNumberChange(value: string) {
@@ -8,7 +8,7 @@
</label>
</div>
<div class="adf-text-widget-container">
<mat-form-field class="adf-form-field-input" [floatLabel]="placeholder ? 'always' : null" subscriptSizing="fixed">
<mat-form-field class="adf-form-field-input" [floatLabel]="placeholder ? 'always' : null" subscriptSizing="dynamic">
@if ( (field.name || this.field?.required) && !field.leftLabels) { <mat-label class="adf-label" [attr.for]="field.id">
{{ field.name | translate }}
</mat-label>