3

I am trying to create a registration form in Angular2, having a "repeat password" functionality. I want this to work using a custom validator as a form-control.

The problem I am having is that the "this-context" seems to be set to the validator when the validator is running so I cant access any local methods on the RegistrationForm class. And I can't seem to find any good way to access the ControlGroup from the validator.

Anyone know a good way to access other controls in the same control-group inside a custom validator?

The is a short sample of the component:

import { Component, View } from 'angular2/angular2';
import { Validators, ControlGroup, Control, FORM_DIRECTIVES, FORM_BINDINGS } from 'angular2/angular2';

@Component({
    selector: 'form-registration'
})
@View({
    directives: [FORM_DIRECTIVES, ROUTER_DIRECTIVES],
    template: `
        <form (submit)="register($event)" [ng-form-model]="registerForm">
            <label for="password1">Password:</label>
            <input id="password1" ng-control="password1" type="password" placeholder="Passord" />

            <label for="password2">Repeat password:</label>
            <input id="password2" ng-control="password2" type="password" placeholder="Gjenta passord" />

            <button class="knapp-submit" type="submit" [disabled]="!registerForm.valid">Registrer deg</button>
        </form>
    `
})
export class RegistrationForm {
    registerForm: ControlGroup;

    constructor() {            
        this.registerForm = new ControlGroup({
            password1: new Control('', Validators.required),
            password2: new Control('', this.customValidator)
        });
    }

    public register(event: Event) {
        // submit form
    }

    private customValidator(control: Control) {
        // check if control is equal to the password1 control
        return {isEqual: control.value === this.registerForm.controls['password1'].value};
    }
}
Salman
  • 9,299
  • 6
  • 40
  • 73
Etse
  • 1,235
  • 1
  • 15
  • 28
  • Have you tried with `this.customValidator.bind(this)` (I think that's the syntax). Another way could be an anonymous function : `new Control('', () => {})` (fat arrows help with context issues for what I've seen) – Eric Martinez Nov 18 '15 at 00:08
  • @EricMartinez this.customValidator.bind(this) works beautifully for me. Cheers! – Sergio Dec 03 '15 at 23:51
  • Worked fine for me aswell. If you add it as an answer I can set it as accepted :) – Etse Dec 04 '15 at 09:39
  • @Etse, can you show you code on how ```this.customValidator.bind(this)``` work? – Bagusflyer Feb 18 '16 at 03:52
  • Still got an error message: **EXCEPTION: Error during instantiation of RegisterPage!.** – Bagusflyer Feb 18 '16 at 04:10

2 Answers2

5

So I solved the problem by binding the customValidator to the this-context of my class as explained in the comment by Sergio.

Keep in mind that the .bind(this) function returns a new instance of the function with the bound-context.

import { Component, View } from 'angular2/angular2';
import { Validators, ControlGroup, Control, FORM_DIRECTIVES, FORM_BINDINGS } from 'angular2/angular2';

@Component({
    selector: 'form-registration'
})
@View({
    directives: [FORM_DIRECTIVES, ROUTER_DIRECTIVES],
    template: `...my form template...`
})
export class RegistrationForm {
    registerForm: ControlGroup;

    constructor() {           
        this.customValidator = this.customValidator.bind(this); 
        this.registerForm = new ControlGroup({
            password1: new Control('', Validators.required),
            password2: new Control('', this.customValidator)
        });
    }

    public register(event: Event) {
        // submit form
    }

    private customValidator(control: Control) {
        // check if control is equal to the password1 control
        return {isEqual: control.value === this.registerForm.controls['password1'].value};
    }
}
Etse
  • 1,235
  • 1
  • 15
  • 28
-3

try to use this code for validation. It works Successfully!!!!

Register.component.html

<div class="signin-content">
    <mat-card>
      <mat-card-content>
        <form [formGroup]="userForm1" (ngSubmit)="onSubmit()">
          <p>Please Register Here</p>
          <mat-input-container class="full-width-input">
            <input matInput placeholder=" First Name" formControlName="firstname" >
          </mat-input-container>
          <mat-input-container class="full-width-input">
            <input matInput  placeholder="Last Name"   formControlName="lastname" >
          </mat-input-container>
          <mat-input-container class="full-width-input">
            <input matInput placeholder="Phone No."   formControlName="phone" required>
            <div *ngIf="userForm1.controls['phone'].hasError('pattern')" class="alert alert-danger" >
                please Enter 10 digits....
            </div>
          </mat-input-container>
          <mat-input-container class="full-width-input">
            <input matInput  placeholder="E-mail"   formControlName="email"  required>
            <span *ngIf="userForm1.hasError('email', 'email') && userForm1.get('email').touched" class="alert-danger">
                Please enter valid email contains '@','.' ...
              </span>
          </mat-input-container>
          <mat-input-container class="full-width-input">
            <input matInput type="password" placeholder="Password"   formControlName="password" required >
          </mat-input-container>
          <mat-input-container class="full-width-input">
            <input matInput type="password" placeholder="Confirm Password"   formControlName="cpassword" required>
            <div  *ngIf="userForm1.controls['cpassword'].errors?.MatchPassword && userForm1.get('cpassword').touched " class="alert alert-danger">
                Password not match
            </div>
          </mat-input-container>
          <button mat-raised-button [disabled]="!userForm1.valid" color="primary" type="submit">Register</button>

        </form>
      </mat-card-content>
    </mat-card>
  </div>

Register.component.ts

import { Component, OnInit, Output, EventEmitter, ViewChild } from '@angular/core';

import { MatGridListModule, MatButtonModule, MatInputModule, MatDialog,MatDialogRef } from '@angular/material';

import { FormGroup, FormBuilder,Validators } from '@angular/forms';

import {HttpClient} from '@angular/common/http';

import { Router } from '@angular/router'

import 'rxjs/add/operator/map';

import { Headers, Http, RequestOptions } from '@angular/http';

import { EqualTextValidator } from "angular2-text-equality-validator";

import { PasswordValidation } from './Passwordvalidation';

@Component({

  selector: 'app-registration',
  templateUrl: './registration.component.html',
  styleUrls: ['./registration.component.css']

})

export class RegistrationComponent implements OnInit {

  userForm1:FormGroup;
  password = 'password';

  constructor( private _formBuilder: FormBuilder,
    // public thisDialogref: MatDialogRef<AppComponent>  ,
    private http:HttpClient,
    private router: Router){}

  ngOnInit() {

    this.userForm1=this._formBuilder.group({

      id:[""],
      firstname:[""],
      lastname: [""],
      phone:[null,[Validators.required, Validators.pattern('^[1-9][0-9]{9}$'),Validators.maxLength(10)]],

      email:[null,[Validators.required,Validators.email]],
      password:["",[Validators.compose([Validators.required])]],
      cpassword:["",[Validators.required]],
      createdDate:[""],
      updatedDate:[""],
      status:[""]
    },{
      validator: PasswordValidation.MatchPassword // your validation method
    })
  }

  onSubmit(){
    console.log(this.userForm1.value);
    this.http.post("http://localhost:4001/user/signup",this.userForm1.value).subscribe(result => {
      console.log("register successful");
     });
     this.router.navigate(['/login']);
  }

}

Passwordvalidation.ts

import {AbstractControl} from '@angular/forms'; export class PasswordValidation {

static MatchPassword(AC: AbstractControl) {
   let password = AC.get('password').value; // to get value in input tag
   let cpassword = AC.get('cpassword').value; // to get value in input tag
    if(password != cpassword) {
        console.log('false');
        AC.get('cpassword').setErrors( {MatchPassword: true} )
    } else {
        console.log('true');
        return null
    }
}

}

Laurent S.
  • 6,816
  • 2
  • 28
  • 40