3

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?

CharithJ
  • 46,289
  • 20
  • 116
  • 131

1 Answers1

0

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

Vishnudev Krishnadas
  • 10,679
  • 2
  • 23
  • 55
  • Thanks for your answer. I tried those two styles but it doesn't work. Also I am more interested in why/how Ivy make such a difference. If there is any hidden Ivy option to fix this behaviour. – CharithJ Feb 23 '21 at 11:42