在提交时验证子组件
validating a child component on submit
我一直在网上寻找,找不到任何答案。
我正在使用 angular 10 和反应形式。
这是我的问题:单击提交按钮会在按钮级别而非子组件级别触发表单的有效性
如果您在此示例中按“保存”,您将仅看到第一个输入触发验证并变为红色,而另一个需要手动单击。我有一个带有 2 个控件的 formGroup
,一个是 FormControl
,另一个是 FormArray
。我将主 formGroup
传递给子组件并在 formArray
中推送 1 formGroup
,这个 formGroup
有一个 formControl
。所以基本上我在叶子上有两个 FormControl
。如果这没有意义,请告诉我。
因此,我希望检查所有元素的有效性,无论它是否在子组件内。
对于诉讼案例,假设您有带有子小部件场景的仪表板
- 这NGX-Sub-Form works well as a turnkey, I like this approach because it breaks up the complexity as a second/level sub form只需扩展其中的4个classes/options
- Angular推荐approach of parent child interaction
下面的示例 来自 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>
现在,如果您将表单对象输出到控制台或任何您可以在表单对象的控件 属性 下看到组件的控件。
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);
}
});
}
您可以像这样在 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。
我一直在网上寻找,找不到任何答案。
我正在使用 angular 10 和反应形式。
这是我的问题:单击提交按钮会在按钮级别而非子组件级别触发表单的有效性
如果您在此示例中按“保存”,您将仅看到第一个输入触发验证并变为红色,而另一个需要手动单击。我有一个带有 2 个控件的 formGroup
,一个是 FormControl
,另一个是 FormArray
。我将主 formGroup
传递给子组件并在 formArray
中推送 1 formGroup
,这个 formGroup
有一个 formControl
。所以基本上我在叶子上有两个 FormControl
。如果这没有意义,请告诉我。
因此,我希望检查所有元素的有效性,无论它是否在子组件内。
对于诉讼案例,假设您有带有子小部件场景的仪表板
- 这NGX-Sub-Form works well as a turnkey, I like this approach because it breaks up the complexity as a second/level sub form只需扩展其中的4个classes/options
- Angular推荐approach of parent child interaction
下面的示例
@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>
现在,如果您将表单对象输出到控制台或任何您可以在表单对象的控件 属性 下看到组件的控件。
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);
}
});
}
您可以像这样在 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。