【问题标题】:validating a child component on submit在提交时验证子组件
【发布时间】:2021-04-28 15:56:28
【问题描述】:

我一直在互联网上寻找答案。

我正在使用 Angular 10 和反应形式。

这是我的问题:点击提交按钮会在按钮级别触发我的表单的有效性,但不会在子组件级别触发

这里是StackBlitz

如果您在此示例中按“保存”,您将看到只有第一个输入触发验证并变为红色,而另一个需要手动单击。我有一个带有 2 个控件的 formGroup,1 个是 FormControl,另一个是 FormArray。我将主要的formGroup 传递给子组件,并在formArray 内推入1 个formGroup,这个formGroup 有一个formControl。所以基本上我在叶子上有两个FormControl。请告诉我这是否没有意义。

因此,我希望检查所有元素的有效性,无论它是否在子组件内。

【问题讨论】:

  • 有人能解释一下否决票

标签: angular angular-reactive-forms


【解决方案1】:

您可以像这样在viewProviders 中使用ControlContainer

control-container.ts

import { Provider, SkipSelf } from '@angular/core';
import { ControlContainer } from '@angular/forms';

export function controlProviderFactory(container: ControlContainer) {
  return container;
}

export const CONTROL_CONTAINER: Provider = {
  provide: ControlContainer,
  useFactory: controlProviderFactory,
  deps: [[new SkipSelf(), ControlContainer]],
};

child.component.ts

import { Component, OnInit, Input } from "@angular/core";
import { FormArray, FormControl, FormGroup, Validators } from "@angular/forms";
import { CONTROL_CONTAINER } from "../control-container";

@Component({
  selector: "app-child",
  templateUrl: "./child.component.html",
  styleUrls: ["./child.component.css"],
  viewProviders: [CONTROL_CONTAINER]
})
export class ChildComponent implements OnInit {
  @Input() public form: FormGroup;

  constructor() {}
  ngOnInit() {}
}

child.component.html

<ng-container formArrayName="subForm">
    <mat-input-container [formGroupName]="0">
    <mat-form-field>
          <input matInput formControlName="subControl">
    </mat-form-field>
    </mat-input-container>
</ng-container>

并在AppComponent的构造函数中初始化:

  constructor (private formBuilder: FormBuilder) {
    this.fg = this.formBuilder.group({
      name: [null, Validators.required],
      subForm: this.formBuilder.array([])
    });

    const control = <FormArray>this.fg.controls['subForm'];

    control.push(this.formBuilder.group({
      subControl: ['', Validators.required]
    }));
  }

有一个错误“当在 FormArray 中添加字段时,提交时不显示 mat-error”。在 GitHub here 上有描述。

基于您的代码的工作示例,您可以找到 here

【讨论】:

  • 谢谢,太好了!你能添加更多关于控制容器对象的解释吗?如果可行,我将实施并标记为已回答
  • 为了在子组件中初始化 formArray,我做了一些更改,并且它起作用了。太好了!!!
【解决方案2】:

Angular 没有自动验证所有表单控件和子表单控件的机制,该任务留给开发人员:

  save() {
    this.validateAllFormFields(this.fg);
  }
  ngOnInit() {
    this.fg = new FormGroup({
      name: new FormControl(
        { value: "", disabled: false },
        Validators.required
      ),
      sub: new FormArray([])
    });
  }

  validateAllFormFields(formGroup: FormGroup | FormArray) {
    Object.keys(formGroup.controls).forEach(field => {
      const control = formGroup.get(field);
      if (control instanceof FormControl) {
        control.markAsTouched({ onlySelf: true });
      } else if (control instanceof FormGroup || control instanceof FormArray) {
        this.validateAllFormFields(control);
      }
    });
  }

【讨论】:

  • 谢谢你的回答,你觉得@transformer的controlValueAccessor方法怎么样?
  • 如果子表单具有直接的 FormControls(即没有深度嵌套的控件),自定义 controlValueAccessor 方法将起作用,我提供的解决方案是用于通用用例
  • ok @karavanjo 似乎是最好的解决方案,尽管我并不了解所有内容。再次感谢您的帮助
【解决方案3】:

对于诉讼案例,假设您有带有子小部件场景的仪表板

  1. 这个NGX-Sub-Form 可以很好地作为一个交钥匙工程,我喜欢这种方法,因为它只需扩展 4 个类/选项之一就可以打破a second/level sub form 的复杂性

  1. 推荐角approach of parent child interaction

下面的例子 borrowed 来自 penley chan

@Directive({
selector: '[provide-parent-form]',
providers: [
    {
        provide: ControlContainer,
        useFactory: function (form: NgForm) {
            return form;
        },
        deps: [NgForm]
    }
  ]
})
export class ProvideParentForm {}

用法:在你的组件根元素之前,你有 [(ngModel)] 添加指令。示例:

<div provide-parent-form> 
   <input name="myInput" [(ngModel)]="myInput"> 
</div>

现在,如果您在控制台中输出表单对象,或者您可以在表单对象的控件属性下看到组件的控件。

【讨论】:

  • 谢谢你的回答,但我已经没有通过这个例子,你的例子使用ngForm我使用反应形式。有什么想法吗?
  • 啊,我明白了,我明天会发布一些内容,但同时这里是一个示例。 indepth.dev/posts/1245/… 那里有 icontrolAccessorValidator... 不记得那是关键
  • 谢谢您,我会检查并等待您的答复
猜你喜欢
  • 2017-04-22
  • 1970-01-01
  • 2014-07-28
  • 1970-01-01
  • 2017-09-04
  • 2023-03-04
  • 2021-04-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多