【问题标题】:Validate child component form when a parent component button is clicked in Angular在Angular中单击父组件按钮时验证子组件表单
【发布时间】:2023-03-13 16:19:01
【问题描述】:

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

父模板:

    <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>

父组件 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
    }
  }
}

子组件模板:

<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>

Stackblitzhttps://stackblitz.com/edit/angular-gyzaag

【问题讨论】:

    标签: angular


    【解决方案1】:

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

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

    formsubmit(){
      this.isShowErrors = true;
      console.log(this.sampleChildForm);
      if(this.sampleChildForm.valid){
        //navigate
      }
    }
    

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

    <child-component #fred [isShowErrors]="isShowErrors"></child-component>
    
    <button type="button" (click)="checkPhone()">Check phone</button>
    

    在父控制器中这样做:

    @ViewChild('fred') fred;
    
    checkPhone() {
      this.fred.formsubmit()
    }
    

    这基本上允许父级调用子级中的方法。这里的关键是#fred 引用变量。当您将引用变量放在 Angular 组件上时,它使您可以访问组件类及其方法,因此您可以轻松地从父级调用 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;
    

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

    【讨论】:

    • 谢谢!就像你说的,这只允许我调用子组件中的方法。由于我希望提交表单状态,因此我尝试在被调用的方法(childComponent)中执行以下操作。 &lt;form #testForm="ngForm"&gt; @ViewChild('testForm') testForm: NgForm this.testForm.ngSubmit.emit() ..但它不会将表单更改为提交状态。
    • 基本上你在包装表单 (form1) 中有一个表单 (form2) - form2 应该在上面的代码中提交 - 如果你提交 form1 那么你将对这两个字段进行验证,因为这两个字段都存在于 form1 中。如果您只想验证一个字段,您可以在提交 form1 之前更改另一个字段的验证,并在提交后恢复另一个字段的验证 - 但听起来有点 hacky。您可能需要考虑使用动态表单,从而可以更改哪些字段属于动态表单。angular.io/guide/dynamic-form
    猜你喜欢
    • 2019-02-22
    • 2018-10-16
    • 2018-06-07
    • 2019-09-01
    • 2018-12-24
    • 2020-05-09
    • 2017-07-15
    • 1970-01-01
    • 2012-12-02
    相关资源
    最近更新 更多