0

I am using a custom validator in my Angular 4 project, when I want to change password I have a popup with 2 fields: password and confirmpassword. In this case both fields are required and when user delete the content of some fields correctly shows error message and field become red. But how can I make field invalid if the password mismatch (make red the fields like required with ng-invalid/has-error)

enter image description here

equalValidator.ts

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,
    @Attribute('reverse') public reverse: string) {

    console.log('Sono in validator')
  }

  private get isReverse() {
    if (!this.reverse) return false;
    return this.reverse === 'true' ? true : false;
  }

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

    // control vlaue
    let e = c.root.get(this.validateEqual);

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

    // value equal and reverse
    if (e && v === e.value && this.isReverse) {
      delete e.errors['validateEqual'];
      if (!Object.keys(e.errors).length) e.setErrors(null);
    }

    // value not equal and reverse
    if (e && v !== e.value && this.isReverse) {
      e.setErrors({
        validateEqual: false
      })
    }

    return null;
  }
}

password.html

<form #modelForm="ngForm">  <div class="form-group">
      <label for="">Password</label>
      <input type="password" class="form-control" name="password" [ngModel]="password" 
        required validateEqual="confirmPassword" reverse="true" #password="ngModel">
      <small [hidden]="password.valid || password.pristine" class="text-danger">
        Password is required
      </small>

    </div>
    <div class="form-group">
      <label for="">Retype password</label>
      <input type="password" class="form-control" name="confirmPassword" [ngModel]="confirmPassword" 
        required validateEqual="password" reverse="false" #confirmPassword="ngModel">
      <small [hidden]="confirmPassword.valid || confirmPassword.pristine " class="text-danger">
        Password mismatch
      </small>

    </div> </form> <p-footer>    <div class="ui-dialog-buttonpane ui-helper-clearfix">  <button class="btn btn-success"         (click)="updatePassword(modelForm, oldPassword.value, password.value, confirmPassword.value)"       [disabled]="((modelForm.form.invalid || modelForm.form.pristine)|| (password.value != confirmPassword.value))">         <span class="btn-label"> <i class="material-icons">check</i>        </span> {{'changepassword.buttons.update' |translate }}     </button> </div>
2
  • Since you are using template-driven form, you can control to hide the mismatch message by just comparing values of password and confirmPassword. Commented Aug 17, 2017 at 9:58
  • @Pengyy I want to make the field red when password mismatch, like when field is required Commented Aug 17, 2017 at 10:01

2 Answers 2

2

Use reactive forms

this.passwordForm = this.fb.group({
    password: [ '', [ Validators.required] ],
    passwordConfirm: [ '', Validators.required ]
}, { validator: this.areEqual });

this i how to create FormGroup.

private areEqual(group: FormGroup) {
    return group.get('password').value === group.get('passwordConfirm').value ? null : { mismatch: true };
}

this is how to validate matching

and then in template you can use

passwordForm?.errors?.mismatch

Hope it'll helps

Sign up to request clarification or add additional context in comments.

2 Comments

The mismatch message is already correct, I want to make invalid the field when password mismatch, at the moment the field is valid if something is typed also if mismatch
don't have to use reactive forms.
1

You could use ngClass to add the bootstrap has-danger class for bootstrap 4, or has-error for previous versions, based on a property set during your validation.

I've simplified your code a little to make the implementation clearer:

  <div class="form-group" [ngClass]="{'has-danger': passwordError}">
    <label class="form-control-label">danger</label>
    <input type="password" class="form-control" name="password"
    required validateEqual="confirmPassword" reverse="true">
  </div>

Here's a working plunkr with the full implementation: https://plnkr.co/edit/MbrFdbd8SVjAhQp3XOOY

2 Comments

It seems that has-error never applied to the field also if I use true: "{'has-error': true}"
Might be your bootstrap version - updated answer with version 4 class, and a plunkr showing it in action.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.