首页 > 解决方案 > 将 ControlValueAccessor 用于 SubForm 的反应式表单在提交时显示错误

问题描述

我有一个简单的登录页面,其中包含一个反应式表单和子表单组件app-login-formControlValueAccessor它正在工作,但我不知道如何在子表单中显示错误。这是我开始创建更复杂表单之前的示例。

提交时,我尝试访问子表单和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();
    });
  }
}

标签: angularangular-formsangular-validation

解决方案


我会采取稍微不同的方法而不是使用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。


推荐阅读