Validador Angular2 que depende de vários campos de formulário

119

É possível criar um validador que pode usar vários valores para decidir se meu campo é válido?

por exemplo, se o método de contato preferido do cliente for por e-mail, o campo de e-mail deve ser obrigatório.

Obrigado.


Atualizado com código de exemplo ...


    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 };
            }
        }

    }
Simon
fonte
Sim. E se você nos mostrar seu código, podemos adicionar uma resposta específica.
Michigan
Eu adicionei um exemplo básico. No código de amostra, como posso validar o código postal apenas se o controle validateZip anterior contiver 'sim'?
Simon
Simon, por que não promover a resposta à sua pergunta?
superjos
6
Ok, para evitar que futuros visitantes desta questão se sintam frustrados, eu recomendo fortemente o uso deste pacote NPM: npmjs.com/package/ng2-validation . Tem construção em equale equalTométodos e boa documentação!
Michelangelo
2
Documentação Angular: angular.io/guide/form-validation#cross-field-validation
ElliotSchmelliot

Respostas:

148

Para reiterar sobre os métodos que outros postaram, é assim que venho criando FormGroupvalidadores que não envolvem vários grupos.

Para este exemplo, basta fornecer os nomes-chave dos campos passworde 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')})

Para Validatorsreceber parâmetros, eles precisam retornar a functioncom FormGroupou FormControlcomo parâmetro. Nesse caso, estou validando a 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
      };
    }
  }
}

Tecnicamente, eu poderia ter validado quaisquer dois valores se soubesse suas chaves, mas prefiro nomear meu Validatorsda mesma forma que o erro que eles retornarão. A função pode ser modificada para receber um terceiro parâmetro que representa o nome da chave do erro retornado.

Atualizado em 6 de dezembro de 2016 (v2.2.4)

Exemplo completo: https://embed.plnkr.co/ukwCXm/

cyber_dave
fonte
@Dave << que não envolvem vários grupos >> Você realmente quis dizer << que envolvem vários grupos >> ou o quê? Obrigado
superjos
Isso não parece remover a marcação de alerta quando as senhas correspondem a Angular 2 RC.1
datatype_void
"ControlGroups" não parece existir no 2.0. Eu usei 'FormGroup'
Stephen
@superjos eu quis dizer isso. Alguns desenvolvedores optam por criar um aninhado FormGrouppara lidar com a validação de vários campos em vez de colocar um Validatorna coisa toda.
cyber_dave
1
E se tivermos senha, confirmPassword e email e Confirm Email? [{validator: matchingPasswords('password', 'confirmPassword')},{validator: matchingEmail('email', 'confirmemail')}] Tentei fazer isso, mas não está funcionando. Alguma sugestão ? @Dave
Sharan Ainapurapu
51

A resposta de Dave foi muito, muito útil. No entanto, uma pequena modificação pode ajudar algumas pessoas.

Caso precise adicionar erros aos Controlcampos, pode-se manter a própria construção do formulário e validadores:

// 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')})

Em vez de definir um erro no ControlGroup, faça-o no campo real da seguinte forma:

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})
    }
  }
}
Louis Cruz
fonte
6
Use passwordConfirmationInput.setErrors(passwordConfirmationInput.validator(passwordConfirmationInput))no elsebranch para atualizá-lo corretamente quando uma mudança para passwordInputtornar os dados válidos.
andraaspar 01 de
@andraaspar Já tentei mas achei o erro TypeError: passwordConfirmationInput.validator is not a function. É porque eu não criei explicitamente o FormControl com Validators.required. Deixei os validadores em branco e, em vez disso, usei o atributo "obrigatório" na entrada.
beardedlinuxgeek 01 de
6
Isso foi útil, mas percebi que a documentação angular tem um tipo de retorno de {[key: string]: any}, que setErrors(...)não retorna (mais?). Também setErrors(...)sobrescreve todos os erros que já estão presentes, então anexei ao objeto de erro atual como: let errors = formGroup.controls[passwordConfirmationKey].errors;and if(!errors) errors={};and errors['notEquivalent'] = true;andformGroup.controls[dateControlFirst].setErrors(errors);
Stephen
32

Ao implementar validadores para vários campos de formulário, você terá que se certificar de que os validadores são reavaliados quando cada um dos controles de formulário é atualizado. A maioria dos exemplos não fornece uma solução para esse cenário, mas isso é muito importante para a consistência dos dados e o comportamento correto.

Consulte minha implementação de um validador personalizado para Angular 2, que leva isso em consideração: https://gist.github.com/slavafomin/17ded0e723a7d3216fb3d8bf845c2f30 .

Estou usando otherControl.valueChanges.subscribe()para ouvir mudanças em outro controle e thisControl.updateValueAndValidity()para acionar outra rodada de validação quando outro controle é alterado.


Estou copiando um código abaixo para referência futura:

match-other-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;

  }

}

Uso

Veja como você pode usá-lo com formas reativas:

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

Validadores mais atualizados podem ser encontrados aqui: moebius-mlm / ng-validators .

Slava Fomin II
fonte
Boa resposta!! Há horas que procuro uma solução como esta! Considere uma pequena mudança: em vez de perder "esta" referência ao retornar uma função, retorne uma função como esta: return (control: FormControl) => {/ * code * /}
Vingtoft
Que bom que pude ajudar. Por que você precisa de referência thispara? Na verdade, é bom ter uma função nomeada para fins de depuração.
Slava Fomin II
Atuação? está funcionando, mas em termos de desempenho, não acho que seja uma boa solução. Atualizar 'thisControl' quando o valor de 'theOtherControl é alterado criará um loop, não é?
nightElf91
Quando deve ser cancelar? othercontrol.valuechanges.subscribenão foi cancelado em qualquer lugar.
juana pu
@juanapu Presumo que o Angular encerrará o valueChangesobservável quando o otherControlfor destruído, o que fará com que a assinatura também seja encerrada. No entanto, suas preocupações podem ser válidas. Eu sugeriria depurar completamente esse código com a versão mais recente do Angular usando vários casos de teste. Por favor, relate novamente se você encontrar quaisquer problemas.
Slava Fomin II
23

Estou usando o Angular 2 RC.5, mas não consegui encontrar o ControlGroup, com base na resposta útil de Dave. Descobri que o FormGroup funciona em vez disso. Então, fiz algumas pequenas atualizações nos códigos de Dave e pensei em compartilhar com outros.

Em seu arquivo de componente, adicione uma importação para FormGroup:

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

Defina suas entradas caso precise acessar o controle de formulário diretamente:

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

Em seu construtor, instancie seu formulário:

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

Adicione a função matchingPasswords em sua classe:

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})
    }
  }
}

Espero que isso ajude aqueles que estão usando o RC.5. Observe que ainda não testei no RC.6.

Chang
fonte
@Sam Você mudou algo para que funcionasse com a versão final? não está funcionando para mim .. Diz: Argumento do tipo '{validator: (group: FormGroup) => void; } 'não é atribuível ao parâmetro do tipo' ValidatorFn '.
dia
Não, eu não precisei mudar nada - para mim, o código de exemplo acima funcionou com o Angular2 final. Você está usando o código exato como acima?
Sam
Boa solução @Chang. Se você alterar sua senha após preencher a senha, confirme. A validação não funciona. Você pode tentarif (passwordInput.value !== passwordConfirmationInput.value) { return passwordConfirmationInput.setErrors({ notEquivalent: true }); } else { return passwordConfirmationInput.setErrors(null); }
Mario Shtika
16

Muitas escavações na fonte angular, mas encontrei uma maneira melhor.

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
    };
}

Parte HTML para grupo de senha

<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>
matthewdaniel
fonte
Quando a validação de matching_password é executada, o controle firstName também é avaliado? O que eu não gostaria!
Pascal
16

Para expandir a resposta de matthewdaniel, uma vez que não é exatamente correta. Aqui está um exemplo de código que mostra como atribuir corretamente um validador a um 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
    };
  }
}

Aqui está um exemplo prático : http://plnkr.co/edit/Zcbg2T3tOxYmhxs7vaAm?p=preview

Cody L.
fonte
e se adicionarmos radiobuttons e checkbox como obter o valor desses dois?
Pardeep Jain
2
ControlGroupé removido em favor de FormGrouppara qualquer um que olhe para isso. Docs and Learn Angular2 Example
apenas
2

Aqui está outra opção que consegui propor que não depende de um subtítulo ou inteiro, ControlGroupmas está diretamente ligada a cada um Control.

O problema que eu tinha era que os controles que eram dependentes um do outro não estavam hierarquicamente juntos, então não consegui criar um ControlGroup. Além disso, meu CSS foi configurado para que cada controle aproveitasse as classes angulares existentes para determinar se exibia um estilo de erro, o que era mais complicado ao lidar com uma validação de grupo em vez de uma validação específica de controle. Tentar determinar se um único controle era válido não foi possível, uma vez que a validação foi vinculada ao grupo de controles e não a cada controle individual.

No meu caso, eu queria o valor de uma caixa de seleção para determinar se outro campo seria obrigatório ou não.

Isso é construído usando o Form Builder no componente. Para o modelo de seleção, em vez de vinculá-lo diretamente ao valor do objeto de solicitação, vinculei-o às funções get / set que me permitirão manipular eventos "on change" para o controle. Então, poderei definir manualmente a validação para outro controle, dependendo do novo valor dos controles selecionados.

Aqui está a parte relevante da visualização:

<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" />

A parte do componente relevante:

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();
    }
  }
}

No meu caso, sempre tive uma validação de padrão ligada ao controle, então o validatoré sempre definido como algo, mas acho que você pode definir o validatorcomo nulo se você não tiver nenhuma validação ligada ao controle.

ATUALIZAÇÃO: Existem outros métodos de captura da mudança do modelo, como (ngModelChange)=changeFunctionName($event)ou inscrição para controlar as mudanças de valor, usandothis.form.controls["employee"].valueChanges.subscribe(data => ...))

Daniel Sara
fonte
1

Também estava procurando por isso e acabou usando equalTodo pacote ng2-validation ( https://www.npmjs.com/package/ng2-validation )

Aqui está um exemplo: Orientado a modelos:

<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>

Orientado por modelo:

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

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

Modelo:

<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
fonte
1

Aqui está minha versão que usei para garantir que uma idade em um campo seja maior ou igual à idade em outro campo. Também estou usando grupos de formulários, então uso a group.getfunção em vez degroup.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 })
        }
    }
}

E no componente:

    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')
    });
Adam Hockemeyer
fonte
0

Acho que sua melhor aposta, por enquanto, é criar um formgroup para manter seus controles. Quando você instancia o seu controle, passe na função para validá-lo. exemplo:

    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;
    });

Eu sei que isso depende muito da versão do angularjs2 que você está executando. Isso foi testado contra 2.0.0-alpha.46

Se alguém tiver uma sugestão melhor como escrever um validador personalizado (que pode ser o melhor caminho a seguir) é bem-vindo.

EDITAR

você também pode usar ControlGroup e validar esse grupo por completo.

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;
    });

Basta editar as mensagens de acordo com o seu domínio.

Bruno Pires Lavigne Quintanilh
fonte
0

A resposta de Louis Cruz foi muito útil para mim.

Para completar, basta adicionar o setErrors reset: return passwordConfirmationInput.setErrors (null);

E tudo funciona bem!

Te agradece,

Saudações,

TGA

TGA
fonte
0

Angular 8 Exemplo de validação no campo de confirmação de senha

Para sua informação: isso não atualizará a validação no campo passwordConfirm se o campo principal "senha" for alterado após a validação ter passado. Mas, você pode invalidar o campo de confirmação de senha quando um usuário digita no campo de senha

<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
    ])
  });
}

password-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')}}
Tim Joyce
fonte
-2

Eu sugeriria usar a biblioteca ng-form-rules. É uma biblioteca incrível para criar todos os diferentes tipos de formulários com lógica de validação desacoplada do componente e que pode depender de alterações de valor de outras áreas no formulário. Eles têm uma ótima documentação , exemplos e um vídeo que mostra muitas de suas funcionalidades . Fazer uma validação como essa o que você está tentando fazer é trivial.

Você pode verificar o README para obter informações de alto nível e um exemplo básico.

Chris Knight
fonte
2
Não gosto da ideia de que tem biblioteca para tudo ... bibliotecas não são a solução para este problema. Freqüentemente, você criará novos problemas apenas com o uso de outra biblioteca, e também terá que manter tudo atualizado quando o Angular for atualizado. Por que não usar formas angulares conforme pretendido pela estrutura?
Nadine,
-3

Regras de validação de correspondência de senha Angular 4.

Se você precisar controlar os erros dos campos, poderá fazê-lo.

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')});
  }

Então você precisa declarar este método no constructormétodo Like as.

constructor(
    private fb: FormBuilder

    ) {
    this.createForm();
  }

Em vez de definir um erro no ControlGroup, faça isso no campo real da seguinte maneira:

    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
      };
    }
  }
}

Parte HTML para grupo de senha

<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
fonte