简体   繁体   English

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

[英]angular how to write directive for crosse field validation for template driven form

So I wanted to create a validator password and confirm password (two fields value should be the same). 因此,我想创建一个验证者密码并确认密码(两个字段的值应该相同)。

This is reachable by create a crosse field validator which get these 2 formControls and compare their values by following this tutorial 这可以通过创建一个crosse字段验证器来实现,该验证器获取这2个formControl并通过遵循本教程比较它们的值

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
}

then, I can set up a reactive form way in my component: 然后,我可以在我的组件中设置反应形式:

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

---- above code works perfect in reactive forms ----上面的代码以反应形式完美地工作

My question is: how to write a Directive for the validator so that I can use it in a Template Driven Way also. 我的问题是:如何为验证程序编写指令,以便我也可以以模板驱动方式使用它。

I tried to write a Directive like following, but this validator is not suppose to work on formControl, but should be on formGroup. 我尝试编写如下指令,但是此验证器不是假定可在formControl上使用,而应在formGroup上。 The following directive can't grab the formGroup and it's controls, so I can't validate the formControls values. 以下指令无法获取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);
  }
}

When I use it in a template like this, I have no luck to get abstractControl instance... 当我在这样的模板中使用它时,我没有运气来获取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>

Change this line: 更改此行:

useExisting: forwardRef(() => FieldMatcherDirective)

And import from @angular/core 并从@angular/core导入

Also, it'll not work because you're getting your ValidatorFn in the constructor. 另外,它也不起作用,因为要在构造函数中获取ValidatorFn。 The field1 and field2 inputs will always be undefined, because they get set before ngOnChanges hook is called. field1和field2输入将始终是未定义的,因为它们是在调用ngOnChanges挂钩之前设置的。 Instead, move that code to ngOnChanges like this: 而是将代码移至ngOnChanges,如下所示:

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

And change the validate() method to this: 并将validate()方法更改为此:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM