Search code examples
cssangularangular-materialstylesmat-input

Style mat input on error (adding a mat icon to input field on error)


I'm trying to style my mat input field on an error by adding an error icon next to the clear field icon like this:

enter image description here

I can't find any way to add the icon. Thank you for your help in advance.

My HTML:

<button
    *ngIf="value"
    matPrefix
    mat-icon-button
    aria-label="Clear"
    (click)="value = ''"
>
    highlight_off
    کلمه جدید 
<input
    class="word-input"
    matInput
    type="text"
    [(ngModel)]="value"
    id="word"
    #wordInput
    required
/>
    error
    کلمه ورودی قبلا وارد شده&zwnj;است

CSS:

::ng-deep .mat-error {
    text-align: right;
    font-size: 12px;
}

:host ::ng-deep .mat-form-field-appearance-outline.mat-form-field-invalid .mat-form-field-outline- thick,
:host ::ng-deep .mat-form-field.mat-form-field-invalid .mat-form-field-label,
.mat-error {
    color: var(--error) !important;
}

Solution

  • Take a look how bootstrap make it in the docs

    then, instead use as class is_invalid you can use .ng-invalid.ng-touched

    .ng-invalid.ng-touched {
        border-color: #dc3545;
        padding-left: calc(1.5em + .75rem) !important;
        background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23dc3545' viewBox='0 0 12 12'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e");
        background-repeat: no-repeat;
        background-position: leftcalc(.375em + .1875rem) center;
        background-size: calc(.75em + .375rem) calc(.75em + .375rem);
    }
    

    NOTE: I change the rigth by left in padding and position the image

    NOTE2: you can use any svg, e.g.

    background-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='%23dc3545' stroke='none' viewBox='0 0 16 16'><path d='M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z'/></svg>");
    

    Update If we are working with material angular, we need take account the "floating label"

    So, we can use in styles.css

    input.ng-invalid.ng-touched {
      border-color: #dc3545;
      padding-left: calc(1.5em) !important;
      background-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='%23dc3545' stroke='none' viewBox='0 0 16 16'><path d='M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z'/></svg>");
      background-repeat: no-repeat;
      background-position: left center;
      background-size: calc(.75em + .375rem) calc(.75em + .375rem);
    }
    mat-form-field.mat-mdc-form-field.ng-invalid.ng-touched:not(.mat-focused) .mat-mdc-floating-label.mdc-floating-label:not(.mdc-floating-label--float-above) {
      transform: translate(1.5em,-.15rem);
    }
    

    See stackblitz