反应式表单使用 ControlValueAccessor 进行子表单在提交时显示错误 [英] Reactive Form Using ControlValueAccessor for SubForm Show Errors on Submit
问题描述
我有一个简单的登录页面,其中包含一个使用 ControlValueAccessor
的响应式表单和子表单组件 app-login-form
,它正在运行,但我无法弄清楚如何在子窗体中显示错误.这是我开始创建更复杂表单之前的一个示例.
I have a simple login page with a reactive form and subform component app-login-form
that uses ControlValueAccessor
, which is working, but I can't figure out how to display the errors in the subform. This is an example before I start creating more complex forms.
提交时,我尝试访问子表单和 markAllAsTouched
,但是当我查看类未更改的元素时.
When submitted I try to access the subform and markAllAsTouched
, but when I'm watching the elements that the classes don't change.
我做了一个快速的StackBlitz 来展示我在做什么.如何在提交表单时显示错误消息?
I made a quick StackBlitz to show what I'm doing. How do I get the error messages to show up when I submit the form?
public onSubmit(event: Event): void {
if (this.form.valid) {
console.log('VALID', this.form.value);
} else {
console.log('INVALID', this.form.value);
Object.keys(this.form.controls).forEach((controlName) => {
console.log('SHOW_ERRORS', controlName);
const control = this.form.get(controlName);
// ISSUE: Nothing changes on the element still ng-untouched, and
// was expecting it to be ng-touched
control.markAllAsTouched();
});
}
}
推荐答案
我会采取稍微不同的方法,不使用 ControlValueAccessor
,而是使用常规"子组件并使用 ControlContainer
,那么你可以跳过所有 markAsTouched
的东西,因为父母会知道孩子身上发生的任何事情.
I would take a slightly different approach and not use ControlValueAccessor
, but instead a "regular" child component and use ControlContainer
, then you can skip all that markAsTouched
stuff, as parent will be aware of anything going on in child.
父母:
this.form = this.formBuilder.group({});
模板:
<app-login-form></app-login-form>
子组件,我们将表单控件添加到现有的父表单中:
Child component, where we add formcontrols to existing parent form:
@Component({
selector: "app-login-form",
templateUrl: "./login-form.component.html",
styleUrls: ["./login-form.component.css"],
viewProviders: [
{
provide: ControlContainer,
useExisting: FormGroupDirective
}
]
})
export class LoginFormComponent implements OnInit {
childForm: FormGroupDirective;
constructor(
parentForm: FormGroupDirective,
private fb: FormBuilder
) {
this.childForm = parentForm;
}
ngOnInit() {
this.childForm.form.addControl('username', this.fb.control('', [Validators.required]));
this.childForm.form.addControl('password', this.fb.control('', [Validators.required]));
}
}
然后在模板中您只需使用 formControlName
而不是 [formControl]
,例如:
Then in template you just use formControlName
instead of [formControl]
, like:
<input matInput formControlName="username">
<mat-error *ngIf="childForm.hasError('required', 'username')">Required</mat-error>
还要去掉child的form标签,还要记得在图标中添加type="button"
,否则按钮将被视为submit
.
Also remove the form tags from child, and also remember to add type="button"
in the icon, otherwise button will be considered submit
.
从父表单提交你可以删除:control.markAllAsTouched();
From parent form submit you can remove: control.markAllAsTouched();
我会用完整的代码对你的 stackblitz 进行分叉,但似乎我不允许分叉.所以希望我记得提到我所做的所有更改,否则请提供一个可以分叉的堆栈闪电战.
这篇关于反应式表单使用 ControlValueAccessor 进行子表单在提交时显示错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!