Валидатор Angular2, который использует несколько полей формы

119

Можно ли создать валидатор, который может использовать несколько значений, чтобы определять, действительно ли мое поле?

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

Спасибо.


Обновлено с помощью примера кода ...


    import {Component, View} from 'angular2/angular2';
    import {FormBuilder, Validators, formDirectives, ControlGroup} from 'angular2/forms';

    @Component({
        selector: 'customer-basic',
        viewInjector: [FormBuilder]
    })
    @View({
        templateUrl: 'app/components/customerBasic/customerBasic.html',
        directives: [formDirectives]
    })
    export class CustomerBasic {
        customerForm: ControlGroup;

        constructor(builder: FormBuilder) {
            this.customerForm = builder.group({
                firstname: [''],
                lastname: [''],
                validateZip: ['yes'],
                zipcode: ['', this.zipCodeValidator] 
                // I only want to validate using the function below if the validateZip control is set to 'yes'
            });
        }

        zipCodeValidator(control) {
            if (!control.value.match(/\d\d\d\d\d(-\d\d\d\d)?/)) {
                return { invalidZipCode: true };
            }
        }

    }
Саймон
источник
Да. И если вы покажете нам свой код, мы сможем добавить конкретный ответ.
michelem 03
Я добавил базовый пример. Как в примере кода проверить почтовый индекс, только если предыдущий элемент управления validateZip содержит «да»?
Саймон
Саймон, почему бы не содействие в ответ на свой вопрос?
superjos 07
6
Хорошо, чтобы избавить будущих посетителей этого вопроса от многих разочарований, я настоятельно рекомендую использовать этот пакет NPM: npmjs.com/package/ng2-validation . Он имеет встроенный в equalи equalToметодах и хорошей документации!
Микеланджело
2
Документация по Angular: angular.io/guide/form-validation#cross-field-validation
ElliotSchmelliot,

Ответы:

148

Чтобы напомнить о методах, которые были опубликованы другими, я создавал FormGroupвалидаторы таким образом, чтобы не задействовать несколько групп.

Для этого примера, просто обеспечивают ключевые имена passwordи confirmPasswordполей.

// Example use of FormBuilder, FormGroups, and FormControls
this.registrationForm = fb.group({
  dob: ['', Validators.required],
  email: ['', Validators.compose([Validators.required,  emailValidator])],
  password: ['', Validators.required],
  confirmPassword: ['', Validators.required],
  firstName: ['', Validators.required],
  lastName: ['', Validators.required]
}, {validator: matchingPasswords('password', 'confirmPassword')})

Чтобы Validatorsполучить параметры, они должны вернуть a functionлибо с a, FormGroupлибо FormControlв качестве параметра. В этом случае я проверяю FormGroup.

function matchingPasswords(passwordKey: string, confirmPasswordKey: string) {
  return (group: FormGroup): {[key: string]: any} => {
    let password = group.controls[passwordKey];
    let confirmPassword = group.controls[confirmPasswordKey];

    if (password.value !== confirmPassword.value) {
      return {
        mismatchedPasswords: true
      };
    }
  }
}

Технически я мог бы проверить любые два значения, если бы знал их ключи, но я предпочитаю называть свое так Validatorsже, как ошибку, которую они вернут. Функцию можно изменить, чтобы она принимала третий параметр, который представляет ключевое имя возвращаемой ошибки.

Обновлено 6 декабря 2016 г. (v2.2.4)

Полный пример: https://embed.plnkr.co/ukwCXm/

cyber_dave
источник
@Dave << которые не включают несколько групп >> Вы действительно имели в виду << которые включают несколько групп >> или что? Спасибо
superjos
Кажется, что это не удаляет разметку предупреждений, когда пароли совпадают с Angular 2 RC.1
datatype_void
"ControlGroups", похоже, не существует в 2.0. Я использовал FormGroup
Стивен
@superjos Я действительно это хотел сказать. Некоторые разработчики предпочитают создавать вложенные файлы FormGroupдля проверки нескольких полей вместо того, чтобы помещать их Validatorна все.
cyber_dave 07
1
Что делать, если у нас есть пароль, confirmPassword и адрес электронной почты, а также подтвердить адрес электронной почты? [{validator: matchingPasswords('password', 'confirmPassword')},{validator: matchingEmail('email', 'confirmemail')}] Я пробовал это, но это не работает. Какие-либо предложения ? @Dave
Sharan Ainapurapu
51

Ответ Дэйва был очень и очень полезным. Однако небольшая модификация может помочь некоторым людям.

В случае, если вам нужно добавить ошибки в Controlполя, вы можете сохранить фактическое построение формы и валидаторов:

// Example use of FormBuilder, ControlGroups, and Controls
this.registrationForm= fb.group({
  dob: ['', Validators.required],
  email: ['', Validators.compose([Validators.required,  emailValidator])],
  password: ['', Validators.required],
  confirmPassword: ['', Validators.required],
  firstName: ['', Validators.required],
  lastName: ['', Validators.required]
}, {validator: matchingPasswords('password', 'confirmPassword')})

Вместо того, чтобы устанавливать ошибку в поле ControlGroup, сделайте это в фактическом поле следующим образом:

function matchingPasswords(passwordKey: string, passwordConfirmationKey: string) {
  return (group: ControlGroup) => {
    let passwordInput = group.controls[passwordKey];
    let passwordConfirmationInput = group.controls[passwordConfirmationKey];
    if (passwordInput.value !== passwordConfirmationInput.value) {
      return passwordConfirmationInput.setErrors({notEquivalent: true})
    }
  }
}
Луи Круз
источник
6
Используйте passwordConfirmationInput.setErrors(passwordConfirmationInput.validator(passwordConfirmationInput))в elseветке, чтобы он обновлялся правильно, когда изменение passwordInputделает данные действительными.
andraaspar 01
@andraaspar Я пробовал, но получил ошибку TypeError: passwordConfirmationInput.validator is not a function. Это потому, что я явно не создавал FormControl с Validators.required. Я оставил валидаторы пустыми и вместо этого использовал атрибут «required» на входе.
beardedlinuxgeek 01
6
Это было полезно, но я заметил, что в документации по angular есть тип возврата {[key: string]: any}, который setErrors(...)не возвращает (больше?). Также setErrors(...)перезаписывает любые ошибки, которые уже присутствуют, поэтому я добавил к текущему объекту ошибки, например: let errors = formGroup.controls[passwordConfirmationKey].errors;и if(!errors) errors={};и errors['notEquivalent'] = true;иformGroup.controls[dateControlFirst].setErrors(errors);
Стивен
32

При реализации валидаторов для нескольких полей формы вам нужно будет убедиться, что валидаторы повторно оцениваются при обновлении каждого элемента управления формы. Большинство примеров не предоставляют решения для такого сценария, но это очень важно для согласованности данных и правильного поведения.

См. Мою реализацию настраиваемого валидатора для Angular 2, которая учитывает это: https://gist.github.com/slavafomin/17ded0e723a7d3216fb3d8bf845c2f30 .

Я использую otherControl.valueChanges.subscribe()для прослушивания изменений в другом элементе управления и thisControl.updateValueAndValidity()для запуска еще одного раунда проверки при изменении другого элемента управления.


Я копирую приведенный ниже код для использования в будущем:

матч-другой-validator.ts

import {FormControl} from '@angular/forms';


export function matchOtherValidator (otherControlName: string) {

  let thisControl: FormControl;
  let otherControl: FormControl;

  return function matchOtherValidate (control: FormControl) {

    if (!control.parent) {
      return null;
    }

    // Initializing the validator.
    if (!thisControl) {
      thisControl = control;
      otherControl = control.parent.get(otherControlName) as FormControl;
      if (!otherControl) {
        throw new Error('matchOtherValidator(): other control is not found in parent group');
      }
      otherControl.valueChanges.subscribe(() => {
        thisControl.updateValueAndValidity();
      });
    }

    if (!otherControl) {
      return null;
    }

    if (otherControl.value !== thisControl.value) {
      return {
        matchOther: true
      };
    }

    return null;

  }

}

использование

Вот как вы можете использовать его с реактивными формами:

private constructForm () {
  this.form = this.formBuilder.group({
    email: ['', [
      Validators.required,
      Validators.email
    ]],
    password: ['', Validators.required],
    repeatPassword: ['', [
      Validators.required,
      matchOtherValidator('password')
    ]]
  });
}

Более современные валидаторы можно найти здесь: moebius-mlm / ng-validators .

Слава Фомин II
источник
Хороший ответ!! Я часами искал подобное решение! Обратите внимание на небольшое изменение: вместо того, чтобы терять ссылку «this» при возврате функции, верните такую ​​функцию: return (control: FormControl) => {/ * code * /}
Vingtoft
Рад, что смог помочь. Зачем нужна ссылка thisдля? На самом деле, хорошо иметь именованную функцию для целей отладки.
Слава Фомин II
Производительность? он работает, но с точки зрения производительности я не думаю, что это хорошее решение. Обновление thisControl при изменении значения theOtherControl создаст цикл, не так ли?
nightElf91
Когда нужно отказываться от подписки? othercontrol.valuechanges.subscribeнигде не отписался.
хуана пу,
@juanapu Я предполагаю, что Angular завершит работу valueChangesнаблюдаемого, когда otherControlон будет уничтожен, что приведет к прекращению подписки. Однако ваши опасения могут быть обоснованными. Я бы посоветовал тщательно отладить этот код в последней версии Angular, используя различные тестовые примеры. Пожалуйста, сообщите, если вы обнаружите какие-либо проблемы.
Слава Фомин II,
23

Я использую Angular 2 RC.5, но не могу найти ControlGroup, основываясь на полезном ответе Дейва. Я обнаружил, что вместо этого работает FormGroup. Так что я немного обновил коды Дэйва и решил поделиться с другими.

В файле компонента добавьте импорт для FormGroup:

import {FormGroup} from "@angular/forms";

Определите свои входы на случай, если вам нужен прямой доступ к элементу управления формой:

oldPassword = new FormControl("", Validators.required);
newPassword = new FormControl("", Validators.required);
newPasswordAgain = new FormControl("", Validators.required);

В конструкторе создайте экземпляр своей формы:

this.form = fb.group({
  "oldPassword": this.oldPassword,
  "newPassword": this.newPassword,
  "newPasswordAgain": this.newPasswordAgain
}, {validator: this.matchingPasswords('newPassword', 'newPasswordAgain')});

Добавьте в свой класс функцию matchPasswords:

matchingPasswords(passwordKey: string, passwordConfirmationKey: string) {
  return (group: FormGroup) => {
    let passwordInput = group.controls[passwordKey];
    let passwordConfirmationInput = group.controls[passwordConfirmationKey];
    if (passwordInput.value !== passwordConfirmationInput.value) {
      return passwordConfirmationInput.setErrors({notEquivalent: true})
    }
  }
}

Надеюсь, это поможет тем, кто использует RC.5. Обратите внимание, что я еще не тестировал RC.6.

Чанг
источник
@Sam Вы что-то меняли, чтобы он работал с финальной версией? это не работает для меня .. Он говорит: Аргумент типа '{validator: (group: FormGroup) => void; } 'не может быть назначен параметру типа' ValidatorFn '.
xtof
Нет, мне не нужно было ничего менять - для меня пример кода выше работал с Angular2 final. Вы используете тот же код, что и выше?
Сэм
Хорошее решение @Chang. Если вы измените свой пароль после ввода пароля подтверждения. Проверка не работает. Вы можете попробоватьif (passwordInput.value !== passwordConfirmationInput.value) { return passwordConfirmationInput.setErrors({ notEquivalent: true }); } else { return passwordConfirmationInput.setErrors(null); }
Марио Штика
16

Много копался в угловом источнике, но я нашел способ получше.

constructor(...) {
    this.formGroup = builder.group({
        first_name:        ['', Validators.required],
        matching_password: builder.group({
            password: ['', Validators.required],
            confirm:  ['', Validators.required]
        }, this.matchPassword)
    });

    // expose easy access to passworGroup to html
    this.passwordGroup = this.formGroup.controls.matching_password;
}

matchPassword(group): any {
    let password = group.controls.password;
    let confirm = group.controls.confirm;

    // Don't kick in until user touches both fields   
    if (password.pristine || confirm.pristine) {
      return null;
    }

    // Mark group as touched so we can add invalid class easily
    group.markAsTouched();

    if (password.value === confirm.value) {
      return null;
    }

    return {
      isValid: false
    };
}

HTML-часть для группы паролей

<div ng-control-group="matching_password" [class.invalid]="passwordGroup.touched && !passwordGroup.valid">
    <div *ng-if="passwordGroup.touched && !passwordGroup.valid">Passwords must match.</div>
    <div class="form-field">
        <label>Password</label>
        <input type="password" ng-control="password" placeholder="Your password" />
    </div>
    <div class="form-field">
        <label>Password Confirmation</label>
        <input type="password" ng-control="confirm" placeholder="Password Confirmation" />
    </div>
</div>
Мэтьюдэниэл
источник
Когда выполняется проверка для match_password, оценивается ли также элемент управления firstName? Кого я бы не хотел!
Паскаль
16

Чтобы расширить ответ Мэтьюданиэля, поскольку это не совсем правильно. Вот пример кода, который показывает, как правильно назначить валидатор для ControlGroup.

import {Component} from angular2/core
import {FormBuilder, Control, ControlGroup, Validators} from 'angular2/common'

@Component({
  selector: 'my-app',
  template: `
    <form [ngFormModel]="form">
      <label for="name">Name:</label>
      <input id="name" type="text" ngControl="name">
      <br>
      <label for="email">Email:</label>
      <input id="email" type="email" ngControl="email">
      <br>
      <div ngControlGroup="matchingPassword">
        <label for="password">Password:</label>
        <input id="password" type="password" ngControl="password">
        <br>
        <label for="confirmPassword">Confirm Password:</label>
        <input id="confirmPassword" type="password" ngControl="confirmPassword">
      </div>
    </form>
    <p>Valid?: {{form.valid}}</p>
    <pre>{{form.value | json}}</pre>
  `
})
export class App {
  form: ControlGroup
  constructor(fb: FormBuilder) {
    this.form = fb.group({
      name: ['', Validators.required],
      email: ['', Validators.required]
      matchingPassword: fb.group({
        password: ['', Validators.required],
        confirmPassword: ['', Validators.required]
      }, {validator: this.areEqual})
    });
  }

  areEqual(group: ControlGroup) {
    let val;
    let valid = true;

    for (name in group.controls) {
      if (val === undefined) {
        val = group.controls[name].value
      } else {
        if (val !== group.controls[name].value) {
          valid = false;
          break;
        }
      }
    }

    if (valid) {
      return null;
    }

    return {
      areEqual: true
    };
  }
}

Вот рабочий пример: http://plnkr.co/edit/Zcbg2T3tOxYmhxs7vaAm?p=preview

Коди Л.
источник
что, если мы добавим радиокнопки и флажок, как получить значение этих двух?
Pardeep Jain
2
ControlGroupудален в пользу FormGroupдля всех, кто смотрит на это. Документы и изучение Пример Angular2
softly
2

Вот еще один вариант, который мне удалось придумать, не зависящий от целого или вспомогательного ControlGroup а напрямую привязан к каждому Control.

Проблема, с которой я столкнулся, заключалась в том, что элементы управления, которые зависели друг от друга, не были иерархически вместе, поэтому я не смог создать ControlGroup. Кроме того, мой CSS был настроен так, что каждый элемент управления будет использовать существующие классы angular, чтобы определить, отображать ли стиль ошибки, что было более сложным при работе с групповой проверкой, а не с проверкой конкретного элемента управления. Попытка определить, был ли действителен отдельный элемент управления, была невозможна, поскольку проверка была привязана к группе элементов управления, а не к каждому отдельному элементу управления.

В моем случае я хотел, чтобы значение поля выбора определяло, требуется ли другое поле или нет.

Это создается с помощью конструктора форм в компоненте. Для модели выбора вместо того, чтобы напрямую связывать ее со значением объекта запроса, я связал ее с функциями получения / установки, которые позволят мне обрабатывать события «при изменении» для элемента управления. Затем я смогу вручную установить проверку для другого элемента управления в зависимости от нового значения элемента управления select.

Вот соответствующая часть просмотра:

<select [ngFormControl]="form.controls.employee" [(ngModel)]="employeeModel">
  <option value="" selected></option>
  <option value="Yes">Yes</option>
  <option value="No">No</option>
</select>
...
<input [ngFormControl]="form.controls.employeeID" type="text" maxlength="255" [(ngModel)]="request.empID" />

Соответствующая составная часть:

export class RequestComponent {
  form: ControlGroup;
  request: RequestItem;

  constructor(private fb: FormBuilder) {
      this.form = fb.group({
        employee: new Control("", Validators.required),
        empID: new Control("", Validators.compose([Validators.pattern("[0-9]{7}"]))
      });

  get employeeModel() {
    return this.request.isEmployee;
  }

  set employeeModel(value) {
    this.request.isEmployee = value;
    if (value === "Yes") {
      this.form.controls["empID"].validator = Validators.compose([Validators.pattern("[0-9]{7}"), Validators.required]);
      this.form.controls["empID"].updateValueAndValidity();
    }
    else {
      this.form.controls["empID"].validator = Validators.compose([Validators.pattern("[0-9]{7}")]);
      this.form.controls["empID"].updateValueAndValidity();
    }
  }
}

В моем случае у меня всегда была проверка шаблона, привязанная к элементу управления, поэтому validatorвсегда установлено что-то, но я думаю, вы можете установитьvalidator значение null, если у вас нет проверки, привязанной к элементу управления.

ОБНОВЛЕНИЕ. Существуют и другие методы регистрации изменений модели, например (ngModelChange)=changeFunctionName($event)подписка на изменения контрольных значений с помощьюthis.form.controls["employee"].valueChanges.subscribe(data => ...))

Даниэль Сара
источник
1

equalToИскал это тоже и в итоге использовал из пакета ng2-validation ( https://www.npmjs.com/package/ng2-validation )

Вот пример: На основе шаблона:

<input type="password" ngModel name="password" #password="ngModel" required/>
<p *ngIf="password.errors?.required">required error</p>
<input type="password" ngModel name="certainPassword" #certainPassword="ngModel" [equalTo]="password"/>
<p *ngIf="certainPassword.errors?.equalTo">equalTo error</p>

Модель с приводом:

let password = new FormControl('', Validators.required);
let certainPassword = new FormControl('', CustomValidators.equalTo(password));

this.form = new FormGroup({
  password: password,
  certainPassword: certainPassword
});

Шаблон:

<form [formGroup]="form">
  <input type="password" formControlName="password"/>
  <p *ngIf="form.controls.password.errors?.required">required error</p>
  <input type="password" formControlName="certainPassword"/>
  <p *ngIf="form.controls.certainPassword.errors?.equalTo">equalTo error</p>
</form>
Baidaly
источник
1

Вот моя версия, которую я использовал для обеспечения того, чтобы возраст в одном поле был больше или равен возрасту в другом поле. Я также использую группы форм, поэтому я использую group.getфункцию, а неgroup.controls[]

import { FormGroup } from '@angular/forms';

export function greaterThanOrEqualTo(sourceKey: string, targetKey: string) {
    return (group: FormGroup) => {
        let sourceInput = group.get(sourceKey);
        let targetInput = group.get(targetKey);

        console.log(sourceInput);
        console.log(targetInput);

        if (targetInput.value < sourceInput.value) {
            return targetInput.setErrors({ notGreaterThanOrEqualTo: true })
        }
    }
}

И в компоненте:

    this.form = this._fb.group({

        clientDetails: this._fb.group({
            currentAge: ['', [Validators.required, Validators.pattern('^((1[89])|([2-9][0-9])|100)$')]],
            expectedRetirementAge: ['', [Validators.required]]
        }),

    },
    {
        validator: greaterThanOrEqualTo('clientDetails.currentAge', 'clientDetails.expectedRetirementAge')
    });
Адам Хокемейер
источник
0

Я думаю, что сейчас лучше всего создать группу форм для хранения элементов управления. Когда вы создаете экземпляр своего Control, передайте функцию для его проверки. пример:

    this.password = new Control('', Validators.required);
    let x = this.password;
    this.confirm = new Control('', function(c: Control){
        if(typeof c.value === 'undefined' || c.value == "") return {required: "password required"};
        if(c.value !== x.value)
            return {error: "password mismatch"};
        return null;
    });

Я знаю, что это сильно зависит от версии angularjs2, которую вы используете. Это было протестировано против 2.0.0-alpha.46

Если у кого-то есть предложение получше, например, написать собственный валидатор (что может быть лучшим способом), мы приветствуем его.

РЕДАКТИРОВАТЬ

вы также можете использовать ControlGroup и полностью проверить эту группу.

this.formGroup = new ControlGroup({}, function(c: ControlGroup){
        var pass: Control = <Control>c.controls["password"];
        var conf: Control = <Control>c.controls["confirm"];
        pass.setErrors(null, true);
        if(pass.value != null && pass.value != ""){
            if(conf.value != pass.value){
                pass.setErrors({error: "invalid"}, true);
                return {error: "error"};
            }
        }
        return null;
    });

Просто отредактируйте сообщения в соответствии с вашим доменом.

Бруно Пирес Лавин Кинтаниль
источник
0

Ответ Луи Круза мне очень помог.

Для завершения просто добавьте в else сброс setErrors: return passwordConfirmationInput.setErrors (null);

И все отлично работает!

Спасибо вам,

С Уважением,

TGA

TGA
источник
0

Angular 8 Пример проверки в поле подтверждения пароля

К вашему сведению: это не обновит проверку в поле passwordConfirm, если основное поле «пароль» будет изменено после того, как эта проверка прошла. Но вы можете аннулировать поле подтверждения пароля, когда пользователь вводит в поле пароля

<input
  type="password"
  formControlName="password"
  (input)="registerForm.get('passwordConfirm').setErrors({'passwordMatches': true})"
/>

register.component.ts

import { PasswordConfirmValidator } from './password-confirm-validator';
export class RegisterComponent implements OnInit {
  registerForm: FormGroup = this.createRegisterForm({
    username: new FormControl('', [Validators.required, Validators.email]),
    password: new FormControl('', [
      Validators.required,
      Validators.pattern('^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9]).{8,}$'),
      Validators.minLength(8)
    ]),
    passwordConfirm: new FormControl('', [
      Validators.required,
      PasswordConfirmValidator //custom validator
    ])
  });
}

пароль-confirm-validator.ts

import { AbstractControl } from '@angular/forms';

export function PasswordConfirmValidator(control: AbstractControl) {
  if(void 0 === control){ return null; }
  if(
    void 0 !== control.parent &&
    void 0 !== control.parent.controls &&
    void 0 !== control.parent.controls['password'] &&
    control.parent.controls['password'].value === control.value
  ){
    return null;
  }
  return {passwordMatches: true};
}

register.component.html

{{registerForm.get('passwordConfirm').hasError('passwordMatches')}}
Тим Джойс
источник
-2

Я бы предложил использовать библиотеку ng-form-rules. Это отличная библиотека для создания всевозможных форм с логикой проверки, отделенной от компонента и которая может зависеть от изменений значений в других областях формы. У них есть отличная документация , примеры и видео, демонстрирующие его функциональность. . Выполняя такую ​​проверку, то, что вы пытаетесь сделать, тривиально.

Вы можете ознакомиться с их README, чтобы получить некоторую высокоуровневую информацию и базовый пример.

Крис Найт
источник
2
Мне не нравится идея, что есть библиотека для всего ... библиотеки не решают эту проблему. Часто вы создаете новые проблемы, просто используя другую библиотеку, также вам нужно поддерживать ее в актуальном состоянии при обновлении Angular. Почему бы не использовать угловые формы, как задумано фреймворком?
Надин
-3

Пароль Angular 4 соответствует правилам проверки.

Если вам нужны поля для контроля ошибок, вы можете это сделать.

createForm() {
    this.ngForm = this.fb.group({
       'first_name': ["", Validators.required ],
       'last_name' : ["", Validators.compose([Validators.required, Validators.minLength(3)]) ],
       'status' : ['active', Validators.compose([Validators.required])],
       'phone':[null],
       'gender':['male'],
       'address':[''],
       'email':['', Validators.compose([
          Validators.required, 
          Validators.email])],
       'password':['', Validators.compose([Validators.required])],
       'confirm_password':['', Validators.compose([Validators.required])]
    }, {validator: this.matchingPassword('password', 'confirm_password')});
  }

Затем вам нужно объявить этот метод в constructorметоде Like as.

constructor(
    private fb: FormBuilder

    ) {
    this.createForm();
  }

Вместо установки ошибки в ControlGroup сделайте это в фактическом поле следующим образом:

    matchingPassword(passwordKey: string, confirmPasswordKey: string) {
  return (group: FormGroup): {[key: string]: any} => {
    let password = group.controls[passwordKey];
    let confirm_password = group.controls[confirmPasswordKey];

    if (password.value !== confirm_password.value) {
      return {        
        mismatchedPasswords: true
      };
    }
  }
}

HTML-часть для группы паролей

<form [formGroup]="ngForm" (ngSubmit)="ngSubmit()">
    <div class="form-group">
            <label class="control-label" for="inputBasicPassword"> Password <span class="text-danger">*</span></label>
                <input type="password" class="form-control" formControlName="password" placeholder="Password" name="password" required>
                <div class="alert text-danger" *ngIf="!ngForm.controls['password'].valid && ngForm.controls['password'].touched">This Field is Required.</div>
            </div>
            {{ngForm.value.password | json}}
            <div class="form-group">
            <label class="control-label" for="inputBasicPassword">Confirm Password <span class="text-danger">*</span></label>
                <input type="password" class="form-control" name="confirm_password" formControlName="confirm_password" placeholder="Confirm Password" match-password="password">

    <div class='alert text-danger' *ngIf="ngForm.controls.confirm_password.touched && ngForm.hasError('mismatchedPasswords')">
              Passwords doesn't match.
      </div>
    </div>
<button type="submit" [disabled]="!ngForm.valid" class="btn btn-primary ladda-button" data-plugin="ladda" data-style="expand-left" disabled="disabled"><span class="ladda-label">
            <i class="fa fa-save"></i>  Create an account
        <span class="ladda-spinner"></span><div class="ladda-progress" style="width: 0px;"></div>
        </span><span class="ladda-spinner"></span></button>
</form>
Md.Jewel Mia
источник