angular - 将 ControlValueAccessor 用于 SubForm 的反应式表单在提交时显示错误
问题描述
我有一个简单的登录页面,其中包含一个反应式表单和子表单组件app-login-form
,ControlValueAccessor
它正在工作,但我不知道如何在子表单中显示错误。这是我开始创建更复杂表单之前的示例。
提交时,我尝试访问子表单和markAllAsTouched
,但是当我查看类不会更改的元素时。
我做了一个快速的StackBlitz来展示我在做什么。提交表单时如何显示错误消息?
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
东西,因为父母会知道孩子身上发生的任何事情。
家长:
this.form = this.formBuilder.group({});
模板:
<app-login-form></app-login-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]
,例如:
<input matInput formControlName="username">
<mat-error *ngIf="childForm.hasError('required', 'username')">Required</mat-error>
还要从子项中删除表单标签,并记得type="button"
在图标中添加,否则将考虑按钮submit
。
从父表单提交中,您可以删除:control.markAllAsTouched();
我会用完整的代码分叉你的堆栈闪电战,但似乎我不允许分叉它。所以希望我记得提到我所做的所有更改,否则请提供一个可以分叉的 stackblitz。