Подтвердить что ты не робот

Проверка поперечного поля в Angular2

Я создаю клиентское приложение Angular2. В настоящее время я работаю над компонентами членства и интегрирую компоненты на стороне клиента с MVC6 vNext Identity v3. Я написал пользовательские Angular2 валидаторы паролей следующим образом:

needsCapitalLetter(ctrl: Control): {[s: string]: boolean} {
    if(!ctrl.value.match(/[A-Z]/))
        return {'needsCapitalLetter': true}

    return null;
}

needsLowerLetter(ctrl: Control): {[s: string]: boolean} {
    if(!ctrl.value.match(/[a-z]/))
        return {'needsLowerLetter': true}

    return null;            
}

needsNumber(ctrl: Control): {[s: string]: boolean} {
    if(!ctrl.value.match(/\d/))
        return {'needsNumber': true}

    return null;            
}

needsSpecialCharacter(ctrl: Control): {[s: string]: boolean} {
    if(!ctrl.value.match(/[^a-zA-Z\d]/))
        return {'needsSpecialCharacter': true}

    return null;            
}

Это отлично работает, и я люблю Angular2, но теперь я пытаюсь написать валидатор, который проверяет, что "Confirm Password" равен "Password". Для этого мне нужно иметь возможность проверять одно поле против другого. Я могу легко сделать это на уровне компонентов, и просто проверить размытие, или отправить, или любое количество других способов, но это обходит систему проверки w490 > ngForm. Я очень хотел бы выяснить, как написать Angular2 Validator для поля, которое может проверять значение другого поля, передавая имя другого поля или что-то близкое к этому. Похоже, что это должна быть возможность, поскольку это было бы необходимо в почти любом сложном пользовательском интерфейсе бизнес-приложений.

4b9b3361

Ответ 1

Вам необходимо назначить валидатор для полной группы форм для его реализации. Что-то вроде этого:

this.form = fb.group({
  name: ['', Validators.required],
  email: ['', Validators.required]
  matchingPassword: fb.group({
    password: ['', Validators.required],
    confirmPassword: ['', Validators.required]
  }, {validator: this.areEqual})  <--------
});

Таким образом, у вас будет доступ ко всем элементам управления группы, а не только к одному... Доступ к этому можно получить, используя свойство controls группового элемента управления. Последний (не один) напрямую предоставляется при срабатывании проверки. Например:

areEqual(group: ControlGroup) {
  var valid = false;

  for (name in group.controls) {
    var val = group.controls[name].value

    (...)
  }

  if (valid) {
    return null;
  }

  return {
    areEqual: true
  };
}

См. этот вопрос для получения дополнительной информации:

Ответ 2

Вы также можете использовать специальный проверочный инструмент для сравнения полей.

В вашем html:

<div>
    <label>Password</label>
    <input type="password" name="password" [ngModel]="user.password" 
        required #password="ngModel">
    <small [hidden]="password.valid || (password.pristine && !f.submitted)">
        Password is required
    </small>
</div>
<div>
    <label>Retype password</label>
    <input type="password" name="confirmPassword" [ngModel]="user.confirmPassword" 
        required validateEqual="password" #confirmPassword="ngModel">
    <small [hidden]="confirmPassword.valid ||  (confirmPassword.pristine && !f.submitted)">
        Password mismatch
    </small>
</div>

И ваша директива:

import { Directive, forwardRef, Attribute } from '@angular/core';
import { Validator, AbstractControl, NG_VALIDATORS } from '@angular/forms';
@Directive({
    selector: '[validateEqual][formControlName],[validateEqual][formControl],[validateEqual][ngModel]',
    providers: [
        { provide: NG_VALIDATORS, useExisting: forwardRef(() => EqualValidator), multi: true }
    ]
})
export class EqualValidator implements Validator {
    constructor( @Attribute('validateEqual') public validateEqual: string) {}

    validate(c: AbstractControl): { [key: string]: any } {
        // self value (e.g. retype password)
        let v = c.value;

        // control value (e.g. password)
        let e = c.root.get(this.validateEqual);

        // value not equal
        if (e && v !== e.value) return {
            validateEqual: false
        }
        return null;
    }
}

Вот полное решение в plunkr:

https://plnkr.co/edit/KgjSTj7VqbWMnRdYZdxM?p=preview

Ответ 3

Я не делал этого сам, но вы могли бы создать ControlGroup с двумя полями пароля и проверить его. Элементы управления имеют свойство .valueChanges, которое является наблюдаемым, и вы можете комбинировать их и проверять наличие там равенства.

Виктор Савкин кратко рассказывает об этом конкретном случае на Angular Воздух в этот эпизод