在 Angular 中单击父组件按钮时验证子组件表单

zer*_*er0 5 angular

我的父模板中有两个按钮。一个按钮充当父/子表单的提交。另一个应该验证子组件表单。单击“提交”按钮即可验证两者 - 这是可以的。但是,我无法使用另一个按钮来验证我的子组件表单。本质上,仅当单击“检查电话”按钮时才显示子表单所需的错误。

父模板:

    <form id="sampleform" [formGroup]="sampleForm" (ngSubmit)="formsubmit()">
  <mat-form-field>
    <input matInput type="text" formControlName="name" [errorStateMatcher]="matcher">
    <mat-error *ngIf="sampleForm.controls.name.hasError('required') && isShowErrors">This field is invalid</mat-error>
  </mat-form-field>
  <br/>
  <br/>
  <child-component [isShowErrors]="isShowErrors"></child-component>
</form>

<button type="button">Check phone</button> <br/>
<button type="submit" form="sampleForm" (click)="formsubmit()">Submit</button>
Run Code Online (Sandbox Code Playgroud)

父组件 TS:

export class AppComponent{
  isShowErrors: boolean = false;
  sampleForm: FormGroup;
  matcher = new MyErrorStateMatcher();
  constructor(private fb: FormBuilder){

  }
  ngOnInit(){
    console.log(">>>>")
    this.sampleForm = this.fb.group({
      name: ['', Validators.required]
    });
  }

  formsubmit(){
    this.isShowErrors = true;
    console.log(this.sampleForm);
    if(this.sampleForm.valid){
      //navigate
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

子组件模板:

<form [formGroup]="sampleChildForm">
  <mat-form-field>
    <input matInput type="text" formControlName="phone" [errorStateMatcher]="matcher">
    <mat-error *ngIf="sampleChildForm.controls.phone.hasError('required') && isShowErrors">Test Error</mat-error>
</mat-form-field>
</form>
Run Code Online (Sandbox Code Playgroud)

堆栈闪电战https://stackblitz.com/edit/angular-gyzaag

dan*_*y74 3

这是一个完整的闪电战...... https://stackblitz.com/edit/angular-7nbjnh ...它实现了此处给出的解决方案。

在子组件控制器中添加此方法:

formsubmit(){
  this.isShowErrors = true;
  console.log(this.sampleChildForm);
  if(this.sampleChildForm.valid){
    //navigate
  }
}
Run Code Online (Sandbox Code Playgroud)

在父组件 html 中更改这些行:

<child-component #fred [isShowErrors]="isShowErrors"></child-component>

<button type="button" (click)="checkPhone()">Check phone</button>
Run Code Online (Sandbox Code Playgroud)

在父控制器中执行以下操作:

@ViewChild('fred') fred;

checkPhone() {
  this.fred.formsubmit()
}
Run Code Online (Sandbox Code Playgroud)

这基本上允许父级调用子级中的方法。这里的关键是#fred参考变量。当您将引用变量放在角度组件上时,您可以访问该组件类及其方法,因此您可以轻松地从父级调用child.formsubmit()AKA 。fred.formsubmit()

此处不相关,但值得了解的是,当您将引用变量放在 HTML 元素上时,它可以让您访问 HTML 元素(以相同的方式getElementById)。

如果有兴趣,这种方法有一个较新的细微变化,它仍然使用@ViewChild但不需要此处的引用变量:

https://angular.io/guide/component-interaction#parent-calls-an-viewchild

这种替代方法基本上是相同的,因为父级仍然调用子级中的方法。连接方式只是略有不同。

如果您想使用替代方案,只需删除引用变量并在父控制器中#fred执行此操作:@ViewChild

import { ChildComponent } from './child/child.component';
@ViewChild(ChildComponent) private fred: ChildComponent;
Run Code Online (Sandbox Code Playgroud)

我个人更喜欢使用引用变量,因为它似乎绑定不太紧密,但我相信后一种方法被认为是最佳实践,因为它位于 Angular 文档中的“组件交互”下。