ramon22
ramon22

Reputation: 3628

Angular material 2 mat-error in child form not showing when submitting forum

Placing a child component with inputs in a parent form and submitting with invalidation will not show the errors in the child component only in the parent. The mat-error in the child will only show when clicked on the inputs.

To replicate the error with this parent Form

  @Component({
      selector: 'lyx-parent-form',
      template: `
  <form novalidate autocomplete="off" role="form" [formGroup]="form" (ngSubmit)="onSubmit()">
    <mat-form-field>
     <input type="password" formControlName="currentPassword" matInput placeholder="current password">
     <mat-error *ngIf="form.get('currentPassword').hasError('required')">current required</mat-error>
    </mat-form-field>

    <lyx-child [form]="form"></lyx-child>

    <button type="submit">submit</button>
  </form>`
    })
    export class ParentFormComponent {
      form: FormGroup;
      constructor(fb: FormBuilder) {
        this.form = fb.group({'currentPassword': ['', [Validators.required]]});
      }  
      onSubmit() {}   
    }

The child component

 @Component({
  selector: 'lyx-child',
  template: `
  <div [formGroup]="form">
    <mat-form-field>
      <input type="password" formControlName="newPassword" matInput placeholder="password">
      <mat-error *ngIf="form.get('newPassword').hasError('required')">Password Required</mat-error>
    </mat-form-field>
   </div>  `
})
export class ChildComponent implements OnInit {
  @Input() form: FormGroup;

  ngOnInit(): void {
    const newPassword = new FormControl('', Validators.compose([Validators.required]));
    this.form.addControl('newPassword', newPassword);
  }
}

Upvotes: 4

Views: 1855

Answers (2)

Jon Cain
Jon Cain

Reputation: 1

I came up with the following solution that works for any number of nested forms. To use this directive, simply add formSubmittedSync to any child form group, e.g., <div [formGroup]="childForm" formSubmittedSync>

import { Directive, SkipSelf } from "@angular/core";
import { FormGroupDirective, ControlContainer } from "@angular/forms";

@Directive({
  selector: '[formSubmittedSync]'
})
export class FormSubmittedSyncDirective {
  constructor(
    @SkipSelf() private parentFormGroupDirective: FormGroupDirective,
    private formGroupDirective: FormGroupDirective) {
    this.parentFormGroupDirective.ngSubmit.asObservable().subscribe(() => {
      (this.formGroupDirective as any).submitted = true;
      this.formGroupDirective.ngSubmit.emit();
    });
  }
}

Upvotes: 0

Nicolas Forney
Nicolas Forney

Reputation: 888

Here is a workaround before I'm able to better understand the way the parent/child form interact.

When submitting the parent form manually set the child "newPassword" control as "touched"

onSubmit(): void {
  this.form.controls.newPassowrd.markAsTouched({onlySelf: true});
}

Upvotes: 4

Related Questions