3
votes

After updating my project from Angular 8 to 9 some of the Angular material mat-form-field controls ended up with weird styling issues.

When comparing the generated code with the old Angular 8 version, I noticed that there are some new css classes (eg:ng-tns-c157-20) added to material input controls. There are many of them and I have found a similar question here . There is a workaround to clear those newly introduced style classes. But that doesn't help in this case.

This happens only when Ivy is enabled, if I disable Ivy from compiler options it doesn't happen and everything works fine.

One of the issues is icon prefix inside a input form-field is overlapping with the label/placeholder. enter image description here

When Ivy is disabled in compiler options it changes as follows, as it was in Angular 8.

enter image description here

Looks like there is a similar bug bug raised in 2018 and still open. However, my issue is only happening when Ivy is enabled.

This is part of the template where I generate input control.

<ng-container *ngIf="formField; else standalone">
    <mat-form-field [appearance]="formField.appearance" [color]="formField.color" [floatLabel]="formField.floatLabel"
        [formGroup]="formField.formGroup" [hideRequiredMarker]="formField.hideRequiredMarker" [hintLabel]="formField.hintLabel">
        <mat-label *ngIf="formField.label">{{formField.label}}</mat-label>
        <ng-template *ngIf="formField.prefix" matPrefix hspElement [context]="context"
            [element]="formField.prefix" (command)="onCommand($event)"></ng-template>
        <input matInput
            [attr.id]="getValue('id')" [ngClass]="getValue('cssClass')" [style.display]="getValue('hidden')?'none':undefined"
            [attr.fieldName]="getValue('placeholder')||undefined" [attr.placeholder]="getValue('placeholder')||undefined"
            [formControlName]="controlName" [required]="required"
            [attr.maxLength]="getValue('maxLength')||undefined" [attr.minLength]="getValue('minLength')||undefined"
            [attr.readonly]="getValue('readOnly')||undefined" [type]="type" (keypress)="onKeyPress($event)" />
        <ng-template *ngIf="formField.suffix" matSuffix hspElement [context]="context"
            [element]="formField.suffix" (command)="onCommand($event)"></ng-template>
        <ng-container *ngFor="let validator of validators" ngProjectAs="mat-error">
            <mat-error *ngIf="hasError(validator)">{{getError(validator)}}</mat-error>
        </ng-container>
    </mat-form-field>
</ng-container>

Disabling Ivy as follows fixes the problem:

angularCompilerOptions": {
    ....
    "enableIvy": false
  }

I am more interested in why Ivy making styling changes. According to Angular 9 update notes it's an under the hood improvement.

Has anyone experienced this? Does anyone know if there is a workaround other than disabling Ivy or adding styling with !important?

1
Can you create a stackblitz to reproduce the exact issue? I have answered regarding the bug that you had mentioned. - Vishnudev
@Vishnudev: Thanks for the reply, unfortunately it's not easy to create a stackblitz sample because we generate UI dynamically based on some JSON inputs. I can show the generated html/angular output if that helps. - CharithJ
But I am not able to reproduce your issue of the icon moving to the top. - Vishnudev
Have you updated Angular Material packages as well? - Sergey
@Sergey: Yes, all angular packages are on v11.1.2 - CharithJ

1 Answers

0
votes

Use these styles in style.scss

.mat-form-field-appearance-fill:not(.mat-focused) .mat-form-field-label {
  margin-top: 0;
}

.mat-form-field-appearance-outline:not(.mat-focused) .mat-form-field-label {
  margin-top: 0.25em;
}

Or, If you want it for a single component, put it in component.scss and set encapsulation of the component to ViewEncapsulation.None

Bug: https://stackblitz.com/edit/angular-xfexy1

Fix using style.scss: https://stackblitz.com/edit/angular-xfexy1-joi5v4

Fix using component.scss: https://stackblitz.com/edit/angular-xfexy1-khj6mi