AAE-35976 Adding auto required instead of manually handling styles manually (#10956)

* AAE-35976 adding auto-required instead of manually handling required using asterisks inside mat-form-field elements

* AAE-35976 removing hiderequiredmarker as it'll be handled by the form-fields itself

Resolving merge conflicts with develop

* AAE-35976 fixing units

* AAE-35976 adding isVisible condition with the required field

* AAE-35976 removing the method call from html and using the variable instead for conditions
This commit is contained in:
Soumyajit Chakraborty
2025-06-26 18:11:24 +05:30
committed by GitHub
parent 056e4c1429
commit 16f42be08e
26 changed files with 250 additions and 130 deletions

View File

@@ -10,10 +10,8 @@
>
</div>
<div>
<mat-form-field class="adf-amount-widget__input adf-form-field-input" [hideRequiredMarker]="true" [floatLabel]="placeholder ? 'always' : null">
<mat-label class="adf-label" *ngIf="!field.leftLabels" [attr.for]="field.id"
>{{field.name | translate }}<span class="adf-asterisk" [style.visibility]="isRequired() ? 'visible' : 'hidden'">*</span></mat-label
>
<mat-form-field class="adf-amount-widget__input adf-form-field-input" [floatLabel]="placeholder ? 'always' : null">
@if ( (field.name || field?.required) && !field.leftLabels) { <mat-label class="adf-label" [attr.for]="field.id">{{field.name | translate }}</mat-label> }
<span matTextPrefix class="adf-amount-widget__prefix-spacing">{{ currency }}&nbsp;</span>
<input
matInput
@@ -21,7 +19,7 @@
class="adf-input"
type="text"
[id]="field.id"
[required]="isRequired()"
[required]="field.required && field.isVisible"
[placeholder]="placeholder"
[value]="field.value"
[(ngModel)]="field.value"

View File

@@ -113,14 +113,14 @@ describe('AmountWidgetComponent', () => {
expect(testingUtils.getByCSS('.adf-invalid')).toBeTruthy();
});
it('should be able to display label with asterisk', async () => {
fixture.detectChanges();
await fixture.whenStable();
it('should be able to display label with asterisk and input field is required', async () => {
const formField = await testingUtils.getMatFormField();
const formControl = await formField.getControl();
const asterisk = testingUtils.getByCSS('.adf-asterisk').nativeElement;
expect(formControl.isRequired).toBeTruthy();
expect(asterisk).toBeTruthy();
expect(asterisk.textContent).toEqual('*');
const inputField = testingUtils.getByCSS('.adf-input').nativeElement;
expect(inputField.hasAttribute('required')).toBeTruthy();
});
});
});
@@ -193,7 +193,7 @@ describe('AmountWidgetComponent - rendering', () => {
expect(await field.getPrefixText()).toBe('$');
const widgetLabel = testingUtils.getByCSS('.adf-label').nativeElement;
expect(widgetLabel.textContent.trim()).toBe('Test Amount*');
expect(widgetLabel.textContent.trim()).toBe('Test Amount');
expect(widget.field.isValid).toBe(false);
const input = await testingUtils.getMatInput();
@@ -229,7 +229,7 @@ describe('AmountWidgetComponent - rendering', () => {
await fixture.whenStable();
const widgetLabel = testingUtils.getByCSS('.adf-label').nativeElement;
expect(widgetLabel.textContent.trim()).toBe('Test Amount*');
expect(widgetLabel.textContent.trim()).toBe('Test Amount');
const field = await testingUtils.getMatFormField();
expect(await field.getPrefixText()).toBe('£');
@@ -311,6 +311,24 @@ describe('AmountWidgetComponent - rendering', () => {
expect(testingUtils.getByCSS('.adf-left-label-input-container')).toBeNull();
expect(testingUtils.getByCSS('.adf-left-label')).toBeNull();
});
it('should be able to display label with manually when left-labels are true', async () => {
widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id', leftLabels: true }), {
id: 'amount-id',
name: 'amount-name',
value: '',
type: FormFieldTypes.AMOUNT,
readOnly: false,
required: true
});
fixture.detectChanges();
await fixture.whenStable();
const asterisk = testingUtils.getByCSS('.adf-asterisk').nativeElement;
expect(asterisk).toBeTruthy();
expect(asterisk.textContent).toEqual('*');
});
});
});

View File

@@ -10,12 +10,17 @@
<div>
<mat-form-field class="adf-date-time-widget adf-form-field-input"
[class.adf-left-label-input-datepicker]="field.leftLabels"
[hideRequiredMarker]="true" [floatLabel]="field.placeholder ? 'always' : null">
<mat-label class="adf-label" *ngIf="!field.leftLabels" [attr.for]="field.id">
{{ field.name | translate }} ({{ field.dateDisplayFormat }})<span class="adf-asterisk" [style.visibility]="isRequired() ? 'visible' : 'hidden'">*</span>
[floatLabel]="field.placeholder ? 'always' : null">
@if( (field.name || field?.required) && !field.leftLabels) {
<mat-label class="adf-label" [attr.for]="field.id">
{{ field.name | translate }} ({{ field.dateDisplayFormat }})
</mat-label>
}
<input matInput
class="adf-input"
[matDatetimepicker]="datetimePicker"
[readonly]="field.readOnly"
[required]="field.required && field.isVisible"
[id]="field.id"
[formControl]="datetimeInputControl"
(keydown.enter)="datetimePicker.open()"

View File

@@ -290,14 +290,6 @@ describe('DateTimeWidgetComponent', () => {
expect(testingUtils.getByCSS('.adf-invalid')).toBeTruthy();
});
it('should be able to display label with asterisk', () => {
fixture.detectChanges();
const asterisk = testingUtils.getByCSS('.adf-asterisk').nativeElement;
expect(asterisk).not.toBeNull();
expect(asterisk?.textContent).toEqual('*');
});
it('should be valid when field is hidden with empty value', () => {
widget.field.isVisible = false;
fixture.detectChanges();
@@ -315,6 +307,16 @@ describe('DateTimeWidgetComponent', () => {
expect(widget.datetimeInputControl.valid).toBeFalse();
expect(widget.field.validationSummary.message).toBe('FORM.FIELD.REQUIRED');
});
it('should be able to display label with asterisk and input field is required', async () => {
const formField = await testingUtils.getMatFormField();
const formControl = await formField.getControl();
expect(formControl.isRequired).toBeTruthy();
const inputField = testingUtils.getByCSS('.adf-input').nativeElement;
expect(inputField.hasAttribute('required')).toBeTruthy();
});
});
describe('template check', () => {
@@ -504,5 +506,19 @@ describe('DateTimeWidgetComponent', () => {
expect(testingUtils.getByDataAutomationId('adf-date-time-widget-picker')).toBeTruthy();
});
it('should be able to display label with asterisk when leftlable is true', () => {
widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id', leftLabels: true }), {
id: 'datetime-id',
name: 'datetime-name',
value: '',
type: FormFieldTypes.DATETIME,
readOnly: false,
required: true
});
fixture.detectChanges();
const asterisk = testingUtils.getByCSS('.adf-asterisk').nativeElement;
expect(asterisk?.textContent).toEqual('*');
});
});
});

View File

@@ -12,6 +12,8 @@
[placeholder]="field.placeholder"
[min]="minDate"
[max]="maxDate"
[required]="field.required && field.isVisible"
[readonly]="field.readOnly"
/>
<mat-datepicker-toggle matSuffix [for]="datePicker" [disabled]="field.readOnly" />
<mat-datepicker #datePicker

View File

@@ -9,17 +9,14 @@
</div>
<div>
<mat-form-field [hideRequiredMarker]="true" class="adf-form-field-input" [floatLabel]="field.placeholder ? 'always' : null">
<mat-label class="adf-label" *ngIf="!field.leftLabels" [attr.for]="field.id">
{{ field.name | translate }}<span class="adf-asterisk" [style.visibility]="isRequired() ? 'visible' : 'hidden'">*</span>
</mat-label>
<mat-form-field class="adf-form-field-input" [floatLabel]="field.placeholder ? 'always' : null">
@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"
type="text"
pattern="-?[0-9]*(\.[0-9]*)?"
[id]="field.id"
[required]="isRequired()"
[required]="field.required && field.isVisible"
[(ngModel)]="field.value"
(ngModelChange)="onFieldChanged(field)"
[disabled]="field.readOnly"

View File

@@ -79,11 +79,14 @@ describe('DecimalComponent', () => {
expect(testingUtils.getByCSS('.adf-invalid')).toBeTruthy();
});
it('should be able to display label with asterisk', async () => {
const asterisk = testingUtils.getByCSS('.adf-asterisk').nativeElement;
it('should be able to display label with asterisk and input field is required', async () => {
const formField = await testingUtils.getMatFormField();
const formControl = await formField.getControl();
expect(asterisk).toBeTruthy();
expect(asterisk?.textContent).toEqual('*');
expect(formControl.isRequired).toBeTruthy();
const inputField = testingUtils.getByCSS('.adf-input').nativeElement;
expect(inputField.hasAttribute('required')).toBeTruthy();
});
});
@@ -147,5 +150,22 @@ describe('DecimalComponent', () => {
const adfLeftLabel = testingUtils.getByCSS('.adf-left-label');
expect(adfLeftLabel).toBeNull();
});
it('should be able to display label with asterisk when leftlabel is true', async () => {
widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id', leftLabels: true }), {
id: 'decimal-id',
name: 'decimal-name',
value: '',
type: FormFieldTypes.DECIMAL,
readOnly: false,
required: true
});
fixture.detectChanges();
const asterisk = testingUtils.getByCSS('.adf-asterisk').nativeElement;
expect(asterisk).toBeTruthy();
expect(asterisk?.textContent).toEqual('*');
});
});
});

View File

@@ -1,23 +1,31 @@
<div class="adf-multiline-text-widget {{ field.className }}"
[class.adf-invalid]="!field.isValid && isTouched()"
[class.adf-readonly]="field.readOnly">
<mat-form-field floatPlaceholder="never" [hideRequiredMarker]="true" class="adf-form-field-input" [floatLabel]="field.placeholder ? 'always' : null">
<mat-label class="adf-label" [attr.for]="field.id">
{{ field.name | translate }}<span class="adf-asterisk" [style.visibility]="isRequired() ? 'visible' : 'hidden'">*</span>
</mat-label>
<textarea matInput
class="adf-input"
[cdkTextareaAutosize]="true"
type="text"
rows="3"
[id]="field.id"
[required]="isRequired()"
[(ngModel)]="field.value"
(ngModelChange)="onFieldChanged(field)"
[disabled]="field.readOnly || readOnly"
[placeholder]="field.placeholder"
[title]="field.tooltip"
(blur)="markAsTouched()">
<div
class="adf-multiline-text-widget {{ field.className }}"
[class.adf-invalid]="!field.isValid && isTouched()"
[class.adf-readonly]="field.readOnly"
>
<mat-form-field
floatPlaceholder="never"
class="adf-form-field-input"
[floatLabel]="field.placeholder ? 'always' : null"
>
@if(field.name || field.required) {
<mat-label class="adf-label" [attr.for]="field.id"> {{ field.name | translate }} </mat-label>
}
<textarea
matInput
class="adf-input"
[cdkTextareaAutosize]="true"
type="text"
rows="3"
[id]="field.id"
[required]="field.required"
[(ngModel)]="field.value"
(ngModelChange)="onFieldChanged(field)"
[disabled]="field.readOnly || readOnly"
[placeholder]="field.placeholder"
[title]="field.tooltip"
(blur)="markAsTouched()"
>
</textarea>
</mat-form-field>
<div *ngIf="field.maxLength > 0" class="adf-multiline-word-counter">
@@ -32,4 +40,3 @@
/>
</div>
</div>

View File

@@ -64,7 +64,8 @@ describe('MultilineTextWidgetComponentComponent', () => {
beforeEach(() => {
widget.field = new FormFieldModel(new FormModel({ taskId: '<id>' }), {
type: FormFieldTypes.MULTILINE_TEXT,
required: true
required: true,
name: 'myField'
});
fixture.detectChanges();
});
@@ -76,11 +77,14 @@ describe('MultilineTextWidgetComponentComponent', () => {
expect(testingUtils.getByCSS('.adf-invalid')).toBeTruthy();
});
it('should be able to display label with asterisk', async () => {
const asterisk = testingUtils.getByCSS('.adf-asterisk').nativeElement;
it('should be able to display label with asterisk and input field is required', async () => {
const formField = await testingUtils.getMatFormField();
const formControl = await formField.getControl();
expect(asterisk).toBeTruthy();
expect(asterisk.textContent).toEqual('*');
expect(formControl.isRequired).toBeTruthy();
const inputField = testingUtils.getByCSS('.adf-input').nativeElement;
expect(inputField.hasAttribute('required')).toBeTruthy();
});
});
});

View File

@@ -9,16 +9,18 @@
</label>
</div>
<div>
<mat-form-field [hideRequiredMarker]="true" class="adf-form-field-input" [floatLabel]="field.placeholder ? 'always' : null">
<mat-label class="adf-label" *ngIf="!field.leftLabels" [attr.for]="field.id">
{{ field.name | translate }}<span class="adf-asterisk" [style.visibility]="isRequired() ? 'visible' : 'hidden'">*</span>
<mat-form-field class="adf-form-field-input" [floatLabel]="field.placeholder ? 'always' : null">
@if( (field.name || this.field?.required) && !field.leftLabels) {
<mat-label class="adf-label" [attr.for]="field.id">
{{ field.name | translate }}
</mat-label>
}
<input matInput
class="adf-input"
type="text"
pattern="-?[0-9]*(\.[0-9]+)?"
[id]="field.id"
[required]="isRequired()"
[required]="field.required"
[value]="displayValue"
[(ngModel)]="field.value"
(ngModelChange)="onNumberChange($event)"

View File

@@ -152,11 +152,14 @@ describe('NumberWidgetComponent', () => {
expect(testingUtils.getByCSS('.adf-invalid')).toBeTruthy();
});
it('should be able to display label with asterisk', async () => {
const asterisk = testingUtils.getByCSS('.adf-asterisk').nativeElement;
it('should be able to display label with asterisk and input field is required', async () => {
const formField = await testingUtils.getMatFormField();
const formControl = await formField.getControl();
expect(asterisk).toBeTruthy();
expect(asterisk.textContent).toEqual('*');
expect(formControl.isRequired).toBeTruthy();
const inputField = testingUtils.getByCSS('.adf-input').nativeElement;
expect(inputField.hasAttribute('required')).toBeTruthy();
});
});
@@ -220,5 +223,22 @@ describe('NumberWidgetComponent', () => {
const adfLeftLabel = testingUtils.getByCSS('.adf-left-label');
expect(adfLeftLabel).toBeNull();
});
it('should be able to display label with asterisk', async () => {
widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id', leftLabels: true }), {
id: 'number-id',
name: 'number-name',
value: '',
type: FormFieldTypes.NUMBER,
readOnly: false,
required: true
});
fixture.detectChanges();
const asterisk = testingUtils.getByCSS('.adf-asterisk').nativeElement;
expect(asterisk).toBeTruthy();
expect(asterisk.textContent).toEqual('*');
});
});
});

View File

@@ -8,15 +8,16 @@
</label>
</div>
<div>
<mat-form-field [hideRequiredMarker]="true" class="adf-form-field-input" [floatLabel]="placeholder ? 'always' : null">
<mat-label *ngIf="!field.leftLabels" class="adf-label" [attr.for]="field.id">
{{ field.name | translate }}<span class="adf-asterisk" [style.visibility]="isRequired() ? 'visible' : 'hidden'">*</span>
<mat-form-field class="adf-form-field-input" [floatLabel]="placeholder ? 'always' : null">
@if ( (field.name || this.field?.required) && !field.leftLabels) { <mat-label class="adf-label" [attr.for]="field.id">
{{ field.name | translate }}
</mat-label>
}
<input matInput
class="adf-input"
type="text"
[id]="field.id"
[required]="isRequired()"
[required]="field.required"
[value]="field.value"
[(ngModel)]="field.value"
(ngModelChange)="onFieldChanged(field)"

View File

@@ -182,14 +182,14 @@ describe('TextWidgetComponent', () => {
expect(testingUtils.getByCSS('.adf-invalid')).toBeTruthy();
});
it('should be able to display label with asterisk', async () => {
fixture.detectChanges();
await fixture.whenStable();
it('should be able to display label with asterisk and input field is required', async () => {
const formField = await testingUtils.getMatFormField();
const formControl = await formField.getControl();
const asterisk = testingUtils.getByCSS('.adf-asterisk').nativeElement;
expect(formControl.isRequired).toBeTruthy();
expect(asterisk).toBeTruthy();
expect(asterisk.textContent).toEqual('*');
const inputField = testingUtils.getByCSS('.adf-input').nativeElement;
expect(inputField.hasAttribute('required')).toBeTruthy();
});
});
@@ -437,5 +437,23 @@ describe('TextWidgetComponent', () => {
expect(adfLeftLabel).toBeNull();
});
});
it('should be able to display label with asterisk', async () => {
widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id', leftLabels: true }), {
id: 'text-id',
name: 'text-name',
value: '',
type: FormFieldTypes.TEXT,
readOnly: false,
required: true
});
fixture.detectChanges();
await fixture.whenStable();
const asterisk = testingUtils.getByCSS('.adf-asterisk').nativeElement;
expect(asterisk).toBeTruthy();
expect(asterisk.textContent).toEqual('*');
});
});
});