Angular 如何编写模板驱动表单的跨字段验证指令

标签 angular angular7

所以我想创建一个验证器密码和确认密码(两个字段值应该相同)。

这可以通过创建一个交叉字段验证器来实现,该验证器获取这两个 formControls 并比较它们的值 by following this tutorial

export function fieldMatcherValidator(field1: string, field2: string): ValidatorFn {
    return (control: AbstractControl): {[key: string]: boolean} | null  => {
    const checkControl = control.get(field1);
    const confirmControl = control.get(field2);
    if (checkControl.pristine || confirmControl.pristine) {
        return null;
    }
    //.....more code compare values
}

然后,我可以在我的组件中设置响应式(Reactive)表单方式:

this.passwordForm = this.fb.group({
      password: new FormControl(undefined, [Validators.required]),
      confirmPassword: new FormControl(undefined, [Validators.required])
    }
    , {validator: fieldMatcherValidator('password', 'confirmPassword')}
    );

---- 上面的代码在响应式(Reactive)形式中完美运行

我的问题是:如何为验证器编写指令,以便我也可以在模板驱动方式中使用它。

我尝试编写如下指令,但该验证器不应该在 formControl 上工作,而应该在 formGroup 上工作。以下指令无法获取 formGroup 及其控件,因此我无法验证 formControls 值。

@Directive({
  selector: '[cmFieldMatcher]',
  providers: [
    {provide: NG_VALIDATORS, useExisting: FieldMatcherDirective, multi: true}
  ]
})
export class FieldMatcherDirective implements Validator {
  @Input() field1: string;
  @Input() field2: string;

  validator: ValidatorFn;

  constructor() {
    this.validator = fieldMatcherValidator(this.field1, this.field2);
  }

  validate(control: AbstractControl) {
    return this.validator(control);
  }
}

当我在这样的模板中使用它时,我没有运气获得abstractControl实例......

<form #form="ngForm" cmFieldMatcher [field1]="'password2'" [field2]="'confirmPassword2'">
                <cm-form-field>
                    <cm-password-input  name="password2" ngModel #password2="ngModel" [label]="'Password'" required [strengthLevel]="passwordStrength" [messages]="passwordMessages">
                    </cm-password-input>
                    <cm-form-field-error  key="fieldMatch" [message]="'Password doesnt match'"></cm-form-field-error>
                </cm-form-field>

                <cm-form-field>
                    <cm-input [type]="'password'" name="confirmPassword2" ngModel #confirmPassword2="ngModel" required [label]="'Confirm Password'" [theme]="'primary'">
                    </cm-input>
                    <cm-form-field-error key="fieldMatch" [message]="'Password doesnt match'"></cm-form-field-error>
                </cm-form-field>
        </form>

最佳答案

更改此行:

useExisting: forwardRef(() => FieldMatcherDirective)

并从@angular/core导入

此外,它也不起作用,因为您在构造函数中获取了 ValidatorFn。 field1 和 field2 输入始终是未定义的,因为它们是在调用 ngOnChanges Hook 之前设置的。相反,将该代码移至 ngOnChanges,如下所示:

ngOnChanges() {
    this.validator = fieldMatcherValidator(this.field1, this.field2);
  }

并将 validate() 方法更改为:

validate(control: AbstractControl) {
    return this.validator ? this.validator(control) : null;
  }

关于 Angular 如何编写模板驱动表单的跨字段验证指令,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54102834/

相关文章:

Angular/AWS Cognito 用户登录错误 - 类型 'refresh' 上不存在属性 'credentials'

java - OAuth token 在浏览器上未经授权

angular - Cdk虚拟滚动问题

javascript - Angular 2 [attr.class] 覆盖原生 DOM 类

Angular 5 通过服务在组件之间进行通信

html - Firebase Cloud Firestore 无法加载数据

javascript - 由于过滤器导致表达式更改而导致 *ngIf 的渲染延迟 - Angular

java - 如何在 Angular post 方法中传递 json 数组以及如何在 Api 中获取该数组?

javascript - 如何从请求返回响应(post | get)?

angular - 如何知道 Observable 的更改值或最终值是否已设置