如何精准控制自定义表单控件的错误提示? [已关闭]

问题描述 投票:0回答:1

我有一个自定义表单控件,里面有许多输入框,以及一些其他组件。当我的自定义验证器验证失败时,我发现所有输入框都读取表单验证失败并设置它们自己变成红色,但事实是它们没有问题,我如何禁用它们自动读取验证状态,并手动控制。

这是我制作的一个简化示例,您可以看到错误已传播到两个控件。如何精确控制错误显示? 示例

angular angular-forms ng-zorro-antd
1个回答
0
投票

问题是错误与

formControl
“myData”有关。

当你有一个

  <nz-form-item>
    <nz-form-label [nzSpan]="7" nzRequired>my custom component</nz-form-label>
    <nz-form-control [nzSpan]="12" nzHasFeedback>
      <app-quality-rule formControlName="myData"></app-quality-rule>
    </nz-form-control>
  </nz-form-item>

ng-zorro 将“ant-input-group-wrapper-status-error”类添加到所有内部“inputs-group”

您可以与班级一起飞行,也可以不使用自定义表单控件并在组件中使用

viewProviders:[{ provide: ControlContainer, useExisting: FormGroupDirective}]

使用viewProviders,一切都改变了。看到现在 validateForm 被称为

this.validateForm = this.fb.group({
  email: ['', [Validators.email, Validators.required]],
  myData: this.fb.group({
    value1: ['', [this.validate('value1')]],
    value2: ['', [this.validate('value2')]],
  }),
});

我们添加自定义函数验证为

  validate(controlName: string) {
    return (control: AbstractControl) => {
      const myData = control.value as MyData;
      const error: any = {};
      if (controlName == 'value1' && !control.value)
        return { [MyDataError.value1Error]: 'value1 error' };

      if (controlName == 'value2' && !control.value)
        return { [MyDataError.value2Error]: 'value2 error' };

      return null;
    };
  }

quality-rile.component 变得更加简单 .ts

import {Component,Input} from '@angular/core';
import {ControlContainer,  FormGroup, FormGroupDirective} from "@angular/forms";
import {MyDataError} from "../app.component";

@Component({
  selector: 'app-quality-rule',
  templateUrl: './quality-rule.component.html',
  viewProviders:[{ provide: ControlContainer, useExisting: FormGroupDirective }]
})
export class QualityRuleComponent  {
  protected readonly MyDataError = MyDataError;
  @Input('group') set _(value:string){
    setTimeout(()=>{
      this.fromControl=this.form.form.get(value) as FormGroup
    })
  }
  fromControl!:FormGroup
  constructor(public form:FormGroupDirective){
  }
}

但是 .html 发生了变化,看看我们如何添加 formGroup 和所有元素,就像我们不拆分表单一样

<ng-container *ngIf="fromControl" [formGroup]="fromControl">
  <nz-form-item>
    <nz-form-control nzHasFeedback>
      <nz-input-group nzAddOnBefore="input1">
        <input formControlName="value1" nz-input />
      </nz-input-group>
    </nz-form-control>
  </nz-form-item>
  <nz-alert
    style="margin-top: 10px;margin-bottom: 5px"
    *ngIf="fromControl?.hasError(MyDataError.value1Error, 'value1')"
    nzType="error"
    [nzDescription]="MyDataError.value1Error"
  ></nz-alert>
  <nz-form-item>
  <nz-form-control nzHasFeedback>
    <nz-input-group nzAddOnBefore="input1">
      <input formControlName="value2" nz-input />
    </nz-input-group>
  </nz-form-control>
</nz-form-item>
  <nz-alert
    style="margin-top: 10px;margin-bottom: 5px"
    *ngIf="fromControl?.hasError(MyDataError.value2Error, 'value2')"
    nzType="error"
    [nzDescription]="MyDataError.value2Error"
  ></nz-alert>
</ng-container>

最后,app.component.html 变成这样

<form nz-form [formGroup]="validateForm">
  <nz-form-item>
    <nz-form-label [nzSpan]="7" nzRequired>E-mail</nz-form-label>
    <nz-form-control [nzSpan]="12" nzHasFeedback>
      <input
        nz-input
        formControlName="email"
        placeholder="email"
        type="email"
      />
    </nz-form-control>
  </nz-form-item>

  <div nz-row>
    <nz-form-label [nzSpan]="7" nzRequired>my custom component</nz-form-label>
    <div nz-col [nzSpan]="12" nzHasFeedback>
      <app-quality-rule group="myData"></app-quality-rule>
    </div>
  </div>
</form>

查看stackblitz

注意:也许,再过一段时间,我会尝试使用自定义表单控件,但我不太确定何时:(

更新一如既往,我们可以利用 Angular 将类添加到我们的输入中并编写一些类似的内容

<nz-form-item>
    ...
        <!--use a template refrence variable "value1"-->
        <input #value1 formControlName="value1" nz-input />
    ...
  </nz-form-item>

  <!--we needn't any more the *ngIf-->
  <nz-alert [ngClass]="{'error-message':true,
                        'ng-invalid':value1.classList.contains('ng-invalid'),
                        'ng-dirty':value1.classList.contains('ng-dirty')}"
    ...></nz-alert>

并用作.css

.error-message{
  display:none
}
.error-message.ng-invalid.ng-dirty{
  display:block
}
© www.soinside.com 2019 - 2024. All rights reserved.