user7435747
user7435747

Reputation: 487

How to display a mat-error message without a form control, but with matInput?

I have this code in my Material table:

<ng-container matColumnDef="columnDef">
   <th mat-header-cell *matHeaderCellDef>Column heading</th>
   <td mat-cell *matCellDef="let row">
       <mat-form-field>
             <input matInput [(ngModel)]="row.myField">
             <mat-error *ngIf="row.myField > 0"> My error message </mat-error>
        </mat-form-field>
   </td>
</ng-container>

The thing is that mat-form-field is not a FormControl, but it would be nice if mat-error would somehow validate this input and display the error message.

Can someone tell me if it is possible?

Upvotes: 26

Views: 36155

Answers (7)

Chris Barr
Chris Barr

Reputation: 34093

If you get a reference to the <mat-chip-list> element you can manually set it's errorState property

@ViewChild('chipList') chipList;

setErrorState(): void {
  this.chipList.errorState = this.dataList.length >= 0;
}

Here's a demo: https://stackblitz.com/edit/angular-matchiplist-with-error-message?file=app%2Fchips-input-example.ts

Upvotes: 0

NewHorse
NewHorse

Reputation: 13

You can use this:

<mat-form-field
  appearance="fill"
  class="mat-input"
  [ngClass]="{ 'mat-form-field-invalid': !!errorMessage }"
  [floatLabel]="'always'"
>
  <mat-label>{{ label }}</mat-label>
  <input
    matInput
    type="text"
    [(ngModel)]="object[valueProperty]"
    (focusout)="onFocusLost()"
  />
  <span class="error" *ngIf="!!errorMessage"> {{ errorMessage }}</span>
</mat-form-field>
  onFocusLost() {
    setTimeout(this.validate, 200);
  }
  
  validate=()=> {
    this.errorMessage = this.validator.ValidationMessage(text);
  }
.error {
  font-size: 10px;
  color: red;
  position: absolute;
  top: 40px;
  left: 0;
}

Upvotes: 0

Yaseer
Yaseer

Reputation: 518

I think following code will give good solution. I have done the auto validation trigger when the user navigated to the component.

Below example implemented for required validation, based on your requirement change the validator

     <mat-form-field>
             <input matInput [(ngModel)]="row.myField" #sampleField="ngModel" required>
             <mat-error *ngIf="sampleField.invalid && (sampleField.errors && sampleField.errors['required'])"> My error message </mat-error>
     </mat-form-field>

If you don't want to auto trigger the validation then can skip the below ts statements

//in ts
     @ViewChild('sampleField', { static: false }) 
     set input(element: NgModel) {
       if(element) {
         element.control.markAllAsTouched()
       }
     }

Upvotes: 2

AlleXyS
AlleXyS

Reputation: 2598

you can use a span attribute with custom style:

<mat-form-field>
      <input matInput [(ngModel)]="row.myField">
      <span *ngIf="row.myField > 0"
             class="error">My error message
      </span>
</mat-form-field>

component.css (this is just an example)

.error {
  font-size: 10px;
  color: red;
}

Upvotes: 5

ronapelbaum
ronapelbaum

Reputation: 1817

While <mat-error> is tied to an error condition of the formControl, <mat-hint> is not.

You can try this hack:

<mat-form-field [class.mat-form-field-invalid]="hasError">
  <input matInput [(ngModel)]="some.model">
  <mat-hint class="mat-error" *ngIf="hasError">Error Message</mat-hint>
</mat-form-field>

Upvotes: 26

ernematthew
ernematthew

Reputation: 403

You are correct that mat-form-field is not a form control, but matInput is. You just need to wrap the input in a form and specify the name for the form control when you are using ngModel binding. You can use the built in min validator on a number type input to do the check for you, then Angular Material will integrate with the FormsModule to hide/show the error as appropriate. The code below should work:

<form>
    <table mat-table>
        ...

        <ng-container matColumnDef="columnDef">
            <th mat-header-cell *matHeaderCellDef>Column heading</th>
            <td mat-cell *matCellDef="let row">
                <mat-form-field>
                    <input matInput type="number" [(ngModel)]="row.myField" [min]="0" [name]="'myField'+row.id">
                    <mat-error>My error message</mat-error>
                </mat-form-field>
            </td>
        </ng-container>

        ...
    </table>
</form>

Note that you need to use a unique row id in the name to make sure that each row gets a unique control in the NgForm. If you don't have a unique column to use you can create a form inside the td element.

Upvotes: 7

Nadhir Falta
Nadhir Falta

Reputation: 5267

<mat-error *ngIf="row.myField.length > 0"> My error message </mat-error>

You are missing the .length of your row.myField > 0

Upvotes: -1

Related Questions