как написать директиву для валидации кросс-полей для шаблонной формы - PullRequest
0 голосов
/ 09 января 2019

Итак, я хотел создать пароль валидатора и подтвердить пароль (значение двух полей должно быть одинаковым).

Это достигается путем создания валидатора кросс-поля, который получает эти 2 formControls и сравнивает их значения , следуя этому руководству

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
}

тогда я могу настроить способ реактивной формы в моем компоненте:

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

---- приведенный выше код прекрасно работает в реактивных формах

У меня вопрос: как написать директиву для валидатора, чтобы я мог использовать ее также на основе шаблонов.

Я пытался написать директиву, подобную следующей, но этот валидатор не должен работать на 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>

1 Ответ

0 голосов
/ 09 января 2019

Изменить эту строку:

useExisting: forwardRef(() => FieldMatcherDirective)

И импорт из @angular/core

Кроме того, это не будет работать, потому что вы получаете ваш ValidatorFn в конструкторе. Входы field1 и field2 всегда будут неопределенными, потому что они устанавливаются до вызова ловушки ngOnChanges. Вместо этого переместите этот код в ngOnChanges следующим образом:

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

И измените метод validate () на этот:

validate(control: AbstractControl) {
    return this.validator ? this.validator(control) : null;
  }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...