Validation Question Please

Hi All,

EDIT: Please ignore this post, and go straight to the first comment.

I have some form validation, which works fine. However, i am trying to also validate that two passwords match (i.e. Password confirm).

My question is, how do I handle validation for multiple fields?

Is there a simpler way of just doing something like this in the html (does not work)?

<div *ngIf="password2 != password1 && password2.touched" class="error-box">* Passwords must match!</div>

The error I get with the example below is:

Error TS2339: Property 'password1' does not exist on type '{ [key: string]: AbstractControl; }'.

and

Error TS2339: Property 'password2' does not exist on type '{ [key: string]: AbstractControl; }'.

Code:

validator.ts

import { Control, ControlGroup } from "@angular/common";
interface ValidationResult {
    [key: string]: boolean;
}
export class Validator {
public static checkFirstCharacterValidator(control: Control): ValidationResult {
var valid = /^\d/.test(control.value);
if (valid) {
    return { checkFirstCharacterValidator: true };
}
return null;

}

public static checkPasswordsMatchrValidator(group: ControlGroup): ValidationResult {
let password1 = group.controls.password1;
let password2 = group.controls.password2;
var valid = password1 === password2;
if (valid) {
    return { checkPasswordsMatchrValidator: true };
}
return null; }}

register.ts

import {Component} from '@angular/core';
import {NavController} from 'ionic-angular';
import {FORM_DIRECTIVES, FormBuilder, ControlGroup, Validators, AbstractControl} from '@angular/common';
import {Validator} from '../validator/validator';
import {CategoryPage} from '../category/category';
import { EmployeeModel } from '../model/EmployeeModel';
@Component({
  templateUrl: 'build/pages/register/register.html',
  directives: [FORM_DIRECTIVES]
})
export class RegisterPage {
  authForm: ControlGroup;
  username: AbstractControl;
  password1: AbstractControl;
  password2: AbstractControl;
  constructor(private nav: NavController, private fb: FormBuilder, private employeeModel: EmployeeModel) {
    this.authForm = fb.group({
      'username': ['', Validators.compose([Validators.required, Validators.minLength(3), Validators.required, Validators.maxLength(25), Validator.checkFirstCharacterValidator])],
      'password1': ['', Validators.compose([Validators.required, Validators.minLength(6), Validators.maxLength(25)])],
      'password2': ['', Validators.compose([Validators.required, Validators.minLength(6), Validator.checkPasswordsMatchrValidator])]
    });
    this.username = this.authForm.controls['username'];
    this.password1 = this.authForm.controls['password1'];
    this.password2 = this.authForm.controls['password2'];
  }

register.html

<ion-content padding>
    <form [ngFormModel]="authForm" (ngSubmit)="onSubmit(authForm.value)">
        <ion-item [class.error]="!username.valid && username.touched">
            <ion-label floating>Username</ion-label>
            <ion-input type="text" value="" [ngFormControl]="username"></ion-input>
        </ion-item>
        <div *ngIf="username.hasError('required') && username.touched" class="error-box">* Username is required!</div>
        <div *ngIf="username.hasError('minlength') && username.touched" class="error-box">* Minimum username length is 3!</div>
        <div *ngIf="username.hasError('maxlength') && username.touched" class="error-box">* Maximum username length is 25!</div>
        <div *ngIf="username.hasError('checkFirstCharacterValidator') && username.touched" class="error-box">* Username cant't start with number!</div>
        <ion-item [class.error]="!password1.valid && password1.touched">
            <ion-label floating>Password</ion-label>
            <ion-input type="password" value="" [ngFormControl]="password1"></ion-input>
        </ion-item>
        <div *ngIf="password1.hasError('required') && password1.touched" class="error-box">* Password is required</div>
        <div *ngIf="password1.hasError('minlength') && password1.touched" class="error-box">* Minimum password length is 6!</div>
        <div *ngIf="password1.hasError('maxlength') && password1.touched" class="error-box">* Maximum password length is 6!</div>
        <ion-item [class.error]="!password2.valid && password2.touched">
            <ion-label floating>Confirm Password</ion-label>
            <ion-input type="password" value="" [ngFormControl]="password2"></ion-input>
        </ion-item>
        <div *ngIf="password2.hasError('required') && password2.touched" class="error-box">* Password is required</div>
        <div *ngIf="password2.hasError('minlength') && password2.touched" class="error-box">* Minimum password length is 6!</div>
        <div *ngIf="password2.hasError('maxlength') && password2.touched" class="error-box">* Maximum password length is 6!</div>
        <br/><br/>
        <button type="submit" primary [disabled]="!authForm.valid" block class="form-button-text">Next</button>
    </form>
</ion-content>

How do I get the following to work? It always returns a true condition (i.e. always displays the error).

<div *ngIf="password2 != password1 && password2.touched" class="error-box">* Passwords must match!</div>

Is the password2 field not found, or is the != not comparing as expected?

Thanks

So the proper way to do this is use the forms module and create a custom validator/form group for the password matchers.

2 Likes

Hi mhartington,

Thank you for the advise. I see I was using an old deprecated version. No I am converting to to the latest (@angular/forms).

But I am getting the following error, do you know what I have done wrong?

EXCEPTION: Error: Uncaught (in promise): Template parse errors:
Can't bind to 'formGroup' since it isn't a known native property ("

html

<ion-header>
  <ion-navbar>
    <button menuToggle>
      <ion-icon name="menu"></ion-icon>
    </button>
    <ion-title>Login</ion-title>
  </ion-navbar>
</ion-header>
<ion-content padding>
    <form [formGroup]="authForm" (ngSubmit)="onSubmit(authForm.value)">
        <ion-item [class.error]="!username.valid && username.touched">
            <ion-label floating>Username</ion-label>
            <ion-input type="text" value="" [formControl]="username"></ion-input>
        </ion-item>
        <div *ngIf="username.hasError('required') && username.touched" class="error-box">* Username is required!</div>
        <div *ngIf="username.hasError('minlength') && username.touched" class="error-box">* Minimum username length is 3!</div>
        <div *ngIf="username.hasError('maxlength') && username.touched" class="error-box">* Maximum username length is 25!</div>
        <div *ngIf="username.hasError('checkFirstCharacterValidator') && username.touched" class="error-box">* Username cant't start with number!</div>
        <ion-item [class.error]="!password.valid && password.touched">
            <ion-label floating>Password</ion-label>
            <ion-input type="password" value="" [formControl]="password"></ion-input>
        </ion-item>
        <div *ngIf="password.hasError('required') && password.touched" class="error-box">* Password is required</div>
        <div *ngIf="password.hasError('minlength') && password.touched" class="error-box">* Minimum password length is 6!</div>
        <div *ngIf="password.hasError('maxlength') && password.touched" class="error-box">* Maximum password length is 25!</div>
        <br/><br/>
        <button type="submit" primary [disabled]="!authForm.valid" block class="form-button-text">Sign in</button>
    </form>
    <br/><br/>
        <text (click)="forgotPassword()" class="small-text">Forgot Password?</text>
    <br/><br/><br/><br/>
        <button light (click)="register()" dark clear block class="form-button-text">Quick Sign up</button>
</ion-content>

ts

import {Component} from '@angular/core';
import {NavController} from 'ionic-angular';
import {FORM_DIRECTIVES, FormBuilder, FormGroup, Validators, AbstractControl} from '@angular/forms';
import {Validator} from '../validator/validator';
import {RegisterPage} from '../register/register';
@Component({
    templateUrl: 'build/pages/login/login.html',
    directives: [FORM_DIRECTIVES]
})
export class LoginPage {
    authForm: FormGroup;
    username: AbstractControl;
    password: AbstractControl;
    constructor(private nav: NavController, private fb: FormBuilder) {
        this.authForm = fb.group({
            'username': ['', Validators.compose([Validators.required, Validators.minLength(3), Validators.required, Validators.maxLength(25), Validator.checkFirstCharacterValidator])],
            'password': ['', Validators.compose([Validators.required, Validators.minLength(6), Validators.maxLength(25)])]
        });
        this.username = this.authForm.controls['username'];
        this.password = this.authForm.controls['password'];
    }
    onSubmit(value: string): void {
        if (this.authForm.valid) {
            console.log('Submitted value: ', value);
        }
    }

and validatior.ts

import { FormControl, FormGroup } from "@angular/forms";
interface ValidationResult {
    [key: string]: boolean;
}
export class Validator {
    public static checkFirstCharacterValidator(control: FormControl): ValidationResult {
        var valid = /^\d/.test(control.value);
        if (valid) {
            return { checkFirstCharacterValidator: true };
        }
        return null;
    }