1

I have a save button outside form. on save button click i want to display mat error. But it does not get displayed. I Tried using this.form.markAsDirty() & this.form.markASTouched() but nothing works.

<form [formGroup]="form">
 <div formArrayName="products" *ngFor="let product of form.get('products').controls; let i = index;">
  <div [formGroupName]="i">
    <mat-form-field>
      <input type="text" formControlName="productCode">
      <mat-error>
          Blank Error
      </mat-error>
    </mat-form-field>
    <mat-form-field>
      <input type="text" formControlName="productName">
      <mat-error>
          Blank Error
      </mat-error>
    </mat-form-field>
   </div>
  </div>
<form>
<div>
   <button type="button" (click)="SaveProducts()">Save</button>
</div>

angular code:

addProduct() {
  this.form.get('products').push(this.getProductGroup())
}

SaveProducts() {
  this.form.markAsDirty();
  this.form.markAsTouched();
  if(this.form.valid) {
     //save products
  }
}
Milad Bahmanabadi
  • 946
  • 11
  • 27
Mayur Patil
  • 303
  • 3
  • 17
  • ` ProductCode is required ` you want show something like that? or You can create custom validator for dirty and touched – Abhishek Dec 09 '18 at 17:41
  • no, i am not looking for that if else – Mayur Patil Dec 09 '18 at 17:49
  • I found the fix. I have to loop through entire formarray and access each FormControl and mark it as touched. Is there a better solution? – Mayur Patil Dec 09 '18 at 17:51
  • Have you look at this link maybe its can be help you because some posible condition are there (https://stackoverflow.com/questions/46745171/angular-material-show-mat-error-on-button-click) – Abhishek Dec 09 '18 at 17:56

1 Answers1

3

Marking the whole FormGroup as touched is not going to make it's children as touched. That's something that you'll have to do explicitly as Angular is not going to do that implicitly. Read this thread for more info on the rationale behind that.

That being said, you can explicitly call markAsTouched on each FormControl in each FormGroup in the 'products' FormArray.

Here's how:

(<FormArray>this.form.get('products')).controls.forEach((group: FormGroup) => {
  (<any>Object).values(group.controls).forEach((control: FormControl) => { 
      control.markAsTouched();
  }) 
});

Here's a Working Sample StackBlitz for your ref.


PS: I've made some more modifications to the mat-errors so that they show up only when the FormFields are touched and are invalid. Also, an ideal user experience would be to disable the Save button in the first place. And show the user an error when they touch the fields. Also, marking the field labels as required(*) can be considered as a good UX.

SiddAjmera
  • 38,129
  • 5
  • 72
  • 110