反应式表单使用 ControlValueAccessor 进行子表单在提交时显示错误 [英] Reactive Form Using ControlValueAccessor for SubForm Show Errors on Submit

查看:19
本文介绍了反应式表单使用 ControlValueAccessor 进行子表单在提交时显示错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个简单的登录页面,其中包含一个使用 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆