Angular:使用多个子组件验证表单

use*_*677 9 angular

在这里使用 Angular 6:

我有一个父组件,其中有 3 个子组件。子组件 1 有一个文本字段,子组件 2 有一个下拉列表,子组件 3 有一个下拉列表和一个提交按钮。

在子 3 的提交单击按钮上,我想验证 child1、child2 和 child3 的所有输入(因为它们是必需的)并相应地抛出错误。

使用 AngularJS,我可以绑定到 ngmodel 并检查表单是否无效。我怎样才能在角度上做到这一点?我的意思是如何获取输入状态并将其从一个孩子传递给另一个孩子等。在搜索时,我发现了反应形式的概念,但大多数文章都是仅具有输入的父母形式。

如果有人可以提供帮助,我将不胜感激。下面是我的代码

- 更新 -

我在关注这篇文章后更新了以下代码: https: //medium.com/@joshblf/using-child-components-in-angular-forms-d44e60036664

但是这个在控制台中不断给我错误:“错误:formControlName必须与父formGroup指令一起使用。您需要添加一个formGroup指令并向其传递一个现有的FormGroup实例(您可以在类中创建一个实例)。

--以反应形式更新了代码--

--Parent--

<form class="form-horizontal" [formGroup]="myForm">
    <div class="row">     
      <ct-child1  [myForm]="myForm"></ct-child1>          
      <ct-child2> </ct-child2>      
    </div>
    <div class="row">      
      <ct-child3></ct-child3>         
    </div>   
</form>

import { Component, OnInit } from '@angular/core';
import { FormGroup, FormBuilder, Validators } from '@angular/forms';

@Component({
  selector: 'ct-parent',
  templateUrl: './parent.component.html']
})
export class ParentComponent implements OnInit  {
  myForm: FormGroup;
  constructor(private fb: FormBuilder) { }
  ngOnInit() {
      this.myForm = this.fb.group({
      uname: ['', Validators.required]
    });
    }  
 }

 --Child 1--

<div class="panel-body">
  <div class="form-group">
    <label for="myForm" class="col-sm-3 control-label">Name:</label>
    <div class="col-sm-8">
      <input type="text" class="form-control" name="uname" [formControlName]="'uname'"  placeholder="Enter Name..." required >
    </div>
  </div>      
</div>

import { Component, OnInit } from '@angular/core';
import { FormGroup } from '@angular/forms';

@Component({
  selector: 'ct-child1',
  templateUrl: './child1.component.html']
})
export class Child1Component implements OnInit { 
  @Input() myForm: FormGroup;
  constructor() { }
  uname: string; 

  ngOnInit() { }
}
Run Code Online (Sandbox Code Playgroud)

AJT*_*T82 5

在父级中构建表单,将所需的任何字段或嵌套表单组传递给子级。父母会知道孩子身上发生的任何事情。它知道特定的表单控件是否有效,整个表单是否有效......它需要了解有关表单的所有信息!

在您的父级中构建表单,传递您想要的任何字段。如果您没有传递给子组件的嵌套表单组,则需要将整个父表单传递给子组件,因为子组件中显示的所有字段都需要包装在表单组内。我们在您的示例中看到的是,您希望将整个表单传递@Input给孩子,就像您一样。然后在您的孩子中,将字段包装在表单组中,就像“常规”表单一样:

<div [formGroup]="myForm">
  <label>Name:</label>
  <input type="text" formControlName="uname"  placeholder="Enter Name...">
</div>      
Run Code Online (Sandbox Code Playgroud)

还要删除 中的括号formControlName,因为您没有尝试使用变量绑定,因此您的表单控件只是简单地命名为uname。此外,您不需要required在模板中进行标记之类的内容,因为这是在您设置Validators.required(或您想要的任何验证器)时由表单处理的。

显示验证错误可以与调用一起使用hasError(),因此在此示例中myForm.hasError('required', 'uname')可以使用 进行设置*ngIf

正如我所提到的,在父级中有提交按钮,因为父级控制着整个表单。我想你可以在子 3 中拥有该按钮,但我认为没有必要让它变得过于复杂,并且需要在树中向上获取父窗体,因为在父窗体中很容易完成,这也是建议如何做:

<form [formGroup]="myForm" (ngSubmit)="onSubmit()">
  <ct-child1 [myForm]="myForm"></ct-child1>
  <button type="submit">Submit</button>
</form>
Run Code Online (Sandbox Code Playgroud)

这是给您的一个示例。只拥有一个孩子,但您可以拥有任意多个不同的孩子,只需遵循与孩子 1 相同的模式即可:)


chr*_*ris 2

我会将子 3 组件中的提交按钮移动到父组件中,然后您可以使用它@ViewChild()来获取对子组件和组件中表单的引用,这将允许您检查它们的有效性。

import { Component, OnInit, ViewChild } from '@angular/core';

@Component({
  selector: 'ct-parent',
  templateUrl: './parent.component.html']
})
export class ParentComponent implements OnInit  {

    @ViewChild(Child1Component) child1Component: Child1Component; 
    @ViewChild(Child2Component) child2Component: Child2Component;
    @ViewChild(Child3Component) child3Component: Child3Component;

    constructor() {}

    ngOnInit() {}  

    submitlClicked() {
        //check if form is valid, else throw error
        if (this.child1Component.myFormGroup.valid 
            && this.child2Component.myFormGroup.valid 
            && this.child3Component.myFormGroup.valid) {
            // do something
        } else {
            // throw error
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

您需要更改代码并使用Reactive Formshttps://angular.io/guide/reactive-forms):

-- Child 1 --

<form [formGroup]="myFormGroup">
  <div class="panel-body">
     <div class="form-group">
         <label class="col-sm-3 control-label">Name:</label>
         <div class="col-sm-8">
             <input type="text" class="form-control" name="uname" formControlName="name" placeholder="Enter Name..." required>
         </div>
      </div>      
   </div>
</form>

import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';

@Component({
  selector: 'ct-child1',
  templateUrl: './child1.component.html']
})
export class Child1Component implements OnInit {

    myFormGroup: FormGroup; 

    constructor(private fb: FormBuilder) {
        myFormGroup = this.fb.group({
            name: ['', Validators.required]
        });
    } 

    ngOnInit() {}
}
Run Code Online (Sandbox Code Playgroud)