表单(嵌入式组件)中可重用,嵌套的子组件,带有验证

时间:2018-05-01 11:22:00

标签: angular forms validation nested

我们说我们有一个地址,并希望以多种形式重复使用它(例如,人,公司......) 在Angular中,一切都是组件,所以我们应该编写一个组件。

最好的方法是什么?事实证明,这并不容易。它应该封装数据并验证嵌入的表单字段。我找到了两个问题的解决方案:

1。自定义表单组件

我不喜欢它:过于复杂,在子组件内部的一切都是委派。 通过验证,您将需要某种内部形式"验证工作。表单控件必须在父级中定义,封装实际上是不可能的。 简单的例子,见: https://stackblitz.com/edit/angular-nested-form-custum-component-test

2。组件,有两个输入:FormGroup和form-submitted-state

来自https://medium.com/spektrakel-blog/angular2-building-nested-reactive-forms-7978ecd145e4

的想法

比自定义表单组件简单得多。我们需要提供在嵌套组件外部构建的FormGroup。 如果我们想要显示验证错误" onSubmit",我们还需要提供表单提交状态'到儿童组件。 简单的例子,见 https://stackblitz.com/edit/angular-nested-formcomponent-test

任何评论或更好的想法来解决问题?

1 个答案:

答案 0 :(得分:1)

Demo

您可以通过将FormGroup传递给具有初始值的嵌套控件来支持封装,并允许嵌套控件定义自己的内部表单组以及任何验证器。

<强> app.component.html

<nested-form-cmp 
     init="foo" 
     [formSubmitted]="f.submitted" 
     [grp]="myForm">
</nested-form-cmp>

AppComponent只需要初始化自己的表单数据:

export class AppComponent  {

  myForm: FormGroup;

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

  submit(form: NgForm) {
    console.log("Reactive Form submitted: " + form.submitted);
  }
}

<强>嵌套form.component.html

嵌套组件将负责创建自己的嵌套FormGroup,并使用验证器初始化它:

<div [formGroup]="grp">
  <div formGroupName="innerGrp">
  <label>
    Inner name:
    <input formControlName="name2" type="text" id="outer"/>   
  </label>
  <span class="error" *ngIf="(formSubmitted || grp.get('innerGrp.name2').touched) && grp.get('innerGrp.name2').hasError('required')">
    Inner name is required
  </span>
  </div>
</div>

<强>嵌套form.component.ts

export class NestedFormComponent implements OnInit{

  // The FormGroup built in the parent
  @Input() public grp: FormGroup;
  @Input() public init: string;

  // Needed, because the FormGroup does not get the forms submitted state
  @Input() public formSubmitted: boolean;
  constructor(private fb: FormBuilder){ 

  }

  ngOnInit() {
    this.grp.setControl('innerGrp', this.fb.group({
      name2: [this.init, Validators.required]
    }))
  }
}