Home  >  Angular

Angular Conditional Validation

By Arvind Rai, July 27, 2018
This page will walk through Angular conditional validation tutorial. We perform conditional validation using valueChanges property or registerOnValidatorChange() method. We subscribe valueChanges of a form control to set and clear validators on any field in reactive form and we call updateValueAndValidity() to recalculate the value and validation status of the control. Using valueChanges we can perform conditional validation for built-in and custom validators both in reactive form. We can create custom validator functions using Angular ValidatorFn and AsyncValidatorFn interfaces and we can create custom validator Directive using Angular Validator and AsyncValidator interfaces. Validator Directive can be used with formControlName, formControl and ngModel. To perform conditional validation using registerOnValidatorChange() we need to create custom validator Directive and define this method. registerOnValidatorChange() is the method of Validator and AsyncValidator interface both. registerOnValidatorChange() registers a function that can be executed conditionally to validate a field. Some built-in validator Directives such as required, email can be conditionally enabled and disabled by assigning boolean values using property binding. Here on this page we will provide complete example to perform conditional validation using valueChanges property and updateValueAndValidity() method for reactive form and we will use registerOnValidatorChange() method for template-driven form.

Technologies Used

Find the technologies being used in our example.
1. Angular 6.0.3
2. Angular CLI 6.0.3
3. TypeScript 2.7.2
4. Node.js 10.3.0
5. NPM 6.1.0

Project Structure

Find the project structure of our demo application.
my-app
|
|--src
|   |
|   |--app 
|   |   |
|   |   |--custom-validators
|   |   |     | 
|   |   |     |--confirm-password-validator.ts 
|   |   |     |--pwd-match-username-validator.ts
|   |   |         
|   |   |--reactive-form.component.ts
|   |   |--reactive-form.component.html
|   |   |--template-driven-form.component.ts
|   |   |--template-driven-form.component.html
|   |   |--user.ts
|   |   |
|   |   |--app.component.ts
|   |   |--app.module.ts 
|   | 
|   |--main.ts
|   |--index.html
|   |--styles.css
|
|--node_modules
|--package.json 

Conditional Custom Validation with valueChanges and updateValueAndValidity()

valueChanges and updateValueAndValidity() are used for conditional validation in reactive form. valueChanges is a property of AbstractControl that emits an event every time when the value of control changes either using UI or programmatically. updateValueAndValidity() is the method of AbstractControl that recalculates the value and validation status of the control. valueChanges and updateValueAndValidity() are available in FormControl, FormArray and FormGroup classes because they inherit AbstractControl class. valueChanges property has been declared as following.
get valueChanges: Observable<any> 
We can see that it returns Observable instance. We can subscribe valueChanges to get data. Here we will perform conditional custom validation by subscribing valueChanges of a FormControl.
Now create a reactive user form.
this.userForm = this.formBuilder.group({
  username: ['', [ Validators.required ]],
  password: ['', [ Validators.required ]],      
  confirmPassword: ['', [ Validators.required ]],          
  notificationMode: ['', [ Validators.required ]],       
  email: '',
  mobileNumber: ''
}); 
1. Username and Password must not match validation

Suppose we want conditional validation that username and password cannot be same. First of all create a custom validator using ValidatorFn.
pwd-match-username-validator.ts
import { AbstractControl, ValidatorFn } from '@angular/forms';

export function pwdMatchUsernameValidator(username: String): ValidatorFn {
  return (control: AbstractControl): {[key: string]: any} | null => {
    let password: string = control.value;
    let isInValid = (password === username) ? true : false;
    return isInValid ? {'matchForUsername': {value: 'Invalid'}} : null;
  };
} 
In the above custom validator we are matching username and password values and if they don't match, then return null and if they match then return error.
Find the getter properties for username and password as following.
get username() {
  return this.userForm.get('username');
}
get password() {
  return this.userForm.get('password');
} 
Now we will create a method inside which we will subscribe valueChanges. By subscribing valueChanges of username and password getter properties, we will set its Validators.
handleFormChanges() {
    this.username.valueChanges.subscribe(
      uname => {
        this.password.setValidators([Validators.required, pwdMatchUsernameValidator(uname)]);
        this.password.updateValueAndValidity();
      }
    );
    this.password.valueChanges.subscribe(
      pwd => {
        const uname = this.username.value;
        this.password.setValidators([Validators.required, pwdMatchUsernameValidator(uname)]);
      }
    );  
} 
Using setValidators() we set synchronous validators and using setAsyncValidators() we set asynchronous validators. Whenever we change value in password field, the password valueChanges subscribe block will execute. Our custom validator pwdMatchUsernameValidator() will execute with current username field value and the password field will be validated.
If password is validated against username and then we change username value, then password field must be revalidated. To revalidate password on change of username, we need to go to password valueChanges subscribe block and set validator for password and then call updateValueAndValidity() on password property as following.
this.password.updateValueAndValidity(); 
The above line will recalculate value and validity status for password field.
Finally to execute handleFormChanges() method we need to call it inside ngOnInit() method.
ngOnInit() {
    this.handleFormChanges();
} 
2. Password and Confirm Password must match validation

Suppose we want to validate password and confirm password fields to be same. We will create a custom validator using ValidatorFn as following.
confirm-password-validator.ts
import { AbstractControl, ValidatorFn } from '@angular/forms';

export function confirmPasswordValidator(confirmPassword: String): ValidatorFn {
  return (control: AbstractControl): {[key: string]: any} | null => {
    let password: string = control.value;
    let isInValid = (password !== confirmPassword) ? true : false;
    return isInValid ? {'cnfPassword': {value: 'Invalid'}} : null;
  };
} 
Create a getter property for confirm password field as following.
get confirmPassword() {
   return this.userForm.get('confirmPassword');
} 
Now find the custom validation code using valueChanges property for username, password and confirm password fields.
handleFormChanges() {
    this.username.valueChanges.subscribe(
      uname => {
        this.password.setValidators([Validators.required, pwdMatchUsernameValidator(uname)]);
        this.password.updateValueAndValidity();
      }
    );
    this.password.valueChanges.subscribe(
      pwd => {
        const uname = this.username.value;
        this.password.setValidators([Validators.required, pwdMatchUsernameValidator(uname)]);

        this.confirmPassword.setValidators([Validators.required, confirmPasswordValidator(pwd)]);        
        this.confirmPassword.updateValueAndValidity();
      }
    );    
    this.confirmPassword.valueChanges.subscribe(
      () => {
        const pwd = this.password.value;
        this.confirmPassword.setValidators([Validators.required, confirmPasswordValidator(pwd)]);
      }
    );     
} 
Above code will ensure that password and username cannot match and password and confirm password must match.

Our HTML template code snippet of reactive form will be as following.
<tr> 
   <td>Username: *</td>
   <td> 
     <input formControlName="username">
     <div *ngIf="username.dirty && username.errors" class = "error"> 
	<div *ngIf="username.errors.required"> 
	  Username required.
	</div>	
     </div>
   </td>
 </tr> 
 <tr> 
   <td>Password: *</td>
   <td> 
     <input formControlName="password" type="password">
     <div *ngIf="password.dirty && password.errors" class = "error"> 
       <div *ngIf="password.errors.required"> 
	   Password required.
       </div>	
       <div *ngIf="password.errors.matchForUsername"> 
	   Password cannot be same as Username.
       </div>					 
     </div>
   </td>
 </tr> 	 
 <tr> 
   <td>Confirm Password: *</td>
   <td> 
     <input formControlName="confirmPassword" type="password">
     <div *ngIf="confirmPassword.dirty && confirmPassword.errors" class = "error"> 
        <div *ngIf="confirmPassword.errors.required"> 
	   Confirm Password required.
        </div>	
        <div *ngIf="confirmPassword.errors.cnfPassword"> 
	   Confirm Password not matched.
        </div>					 
     </div>
   </td>
 </tr> 

Conditional Custom Validation with registerOnValidatorChange()

To use conditional custom validation with formControlName, formControl and ngModel we need to create custom validator Directive using Validator or AsyncValidator interface. Validator creates synchronous custom validator and AsyncValidator creates asynchronous custom validator. Validator and AsyncValidator has following method declarations.
validate(): It validates the value.
registerOnValidatorChange(): It registers a function that can be called to revalidate the value.

Let us understand how to register a function using registerOnValidatorChange().
Declare a function as following.
private _onChange: () => void; 
Register the above function with registerOnValidatorChange().
registerOnValidatorChange(fn: () => void): void { this._onChange = fn; } 
Now whenever we call _onChange(), it will execute validate() method to revalidate value. Using ngOnChanges() we can track the changes in value of @Input properties of our validator Directive and conditionally we can call our registered function _onChange(). In this way we can achieve conditional validation.

1. Username and Password must not match validation

We will create a validator Directive for conditional custom validation that password cannot match username.
pwd-match-username-validator.ts
import { Directive, Input, OnChanges , SimpleChanges } from '@angular/core';
import { AbstractControl, NG_VALIDATORS, Validator, ValidatorFn } from '@angular/forms';

export function pwdMatchUsernameValidator(username: String): ValidatorFn {
  return (control: AbstractControl): {[key: string]: any} | null => {
    let password: string = control.value;
    let isInValid = (password === username) ? true : false;
    return isInValid ? {'matchForUsername': {value: 'Invalid'}} : null;
  };
}

@Directive({
  selector: '[matchForUsername][formControlName],[matchForUsername][formControl],[matchForUsername][ngModel]',
  providers: [{provide: NG_VALIDATORS, useExisting: PwdMatchUsernameValidatorDirective, multi: true}]
})
export class PwdMatchUsernameValidatorDirective implements Validator, OnChanges {
  @Input('matchForUsername')
  changedUsername: string;
  private _onChange: () => void;

  validate(control: AbstractControl): {[key: string]: any} | null {
    return this.changedUsername ? 
        pwdMatchUsernameValidator(this.changedUsername)(control): null;
  }

  registerOnValidatorChange(fn: () => void): void { this._onChange = fn; }

  ngOnChanges(changes: SimpleChanges) {
    if ('changedUsername' in changes) {
      if (this._onChange) this._onChange();
    }
  }  
} 
To ensure that if username is changed then password must be revalidated, we are using ngOnChanges() method that executes when any data-bound property of the Directive changes. For any change in changedUsername property of Directive, we are executing _onChange() function to revalidate password.

2. Password and Confirm Password must match validation

In the same way as above if we want conditional custom validation to ensure that password and confirm password must match, we can create custom validator Directive as following.
confirm-password-validator.ts
import { Directive, Input, OnChanges , SimpleChanges } from '@angular/core';
import { AbstractControl, NG_VALIDATORS, Validator, ValidatorFn } from '@angular/forms';

export function confirmPasswordValidator(confirmPassword: String): ValidatorFn {
  return (control: AbstractControl): {[key: string]: any} | null => {
    let password: string = control.value;
    let isInValid = (password !== confirmPassword) ? true : false;
    return isInValid ? {'cnfPassword': {value: 'Invalid'}} : null;
  };
}

@Directive({
  selector: '[cnfPassword][formControlName],[cnfPassword][formControl],[cnfPassword][ngModel]',
  providers: [{provide: NG_VALIDATORS, useExisting: ConfirmPasswordValidatorDirective, multi: true}]
})
export class ConfirmPasswordValidatorDirective implements Validator, OnChanges {
  @Input('cnfPassword')
  confirmPassword: string;
  private _onChange: () => void;

  validate(control: AbstractControl): {[key: string]: any} | null {
    return this.confirmPassword ? 
          confirmPasswordValidator(this.confirmPassword)(control): null;
  }

  registerOnValidatorChange(fn: () => void): void { this._onChange = fn; }

  ngOnChanges(changes: SimpleChanges) {
    if ('confirmPassword' in changes) {
      if (this._onChange) this._onChange();
    }
  }  
} 
In the above code inside ngOnChanges() method, we are executing _onChange() function to revalidate confirm password for any change in password.

We need to configure custom validator Directive in application module within declarations block of @NgModule as following.
app.module.ts
import { PwdMatchUsernameValidatorDirective } from './custom-validators/pwd-match-username-validator';
import { ConfirmPasswordValidatorDirective } from './custom-validators/confirm-password-validator';

@NgModule({
  declarations: [
      ------
      PwdMatchUsernameValidatorDirective,
      ConfirmPasswordValidatorDirective
  ],
  ------
})
export class AppModule { } 
We can use custom validator Directive with formControlName, formControl and ngModel. Find the HTML template code snippet for template-driven form with our validator Directive.
<tr> 
   <td>Username: *</td>
   <td> 
      <input name="username" required ngModel #uname="ngModel">
      <div *ngIf="uname.dirty && uname.errors" class = "error"> 
	<div *ngIf="uname.errors.required"> 
	   Username required.
	</div>	
      </div>
   </td>
 </tr> 
 <tr> 
   <td>Password: *</td>
   <td> 
     <input type="password" name="password" required [matchForUsername]="uname.value" ngModel #pwd="ngModel">
     <div *ngIf="pwd.dirty && pwd.errors" class = "error"> 
        <div *ngIf="pwd.errors.required"> 
	   Password required.
        </div>	
	<div *ngIf="pwd.errors.matchForUsername"> 
     	   Password cannot be same as Username.
	</div>		
     </div>
    </td>
 </tr> 	 
 <tr> 
   <td>Confirm Password: *</td>
   <td> 
     <input type="password" name="confirmPassword" required [cnfPassword]="pwd.value" ngModel #cnfPwd="ngModel">
     <div *ngIf="cnfPwd.dirty && cnfPwd.errors" class = "error"> 
	<div *ngIf="cnfPwd.errors.required"> 
  	   Confirm Password required.
	</div>	
	<div *ngIf="cnfPwd.errors.cnfPassword"> 
  	   Confirm Password not matched.
	</div>		
     </div>
    </td>
 </tr> 

Conditional Validation with Built-in Validators

Here we will use built-in validators such as required, email for conditional validations. Suppose we have three notification mode i.e. email, mobile number and both and we want that if email is selected then validation should be applied only on email field, if mobile number is selected then validation should be applied only on mobile number field, if both option is selected then validation should be applied on both fields email and mobile number. To achieve this conditional validation we can use valueChanges or expressions that returns boolean value.

1. Using valueChanges and updateValueAndValidity()

valueChanges will be helpful in reactive form. Suppose we have getter properties for notification mode, email and mobile number as following.
get notificationMode() {
  return this.userForm.get('notificationMode');
}        
get email() {
  return this.userForm.get('email');
}  
get mobileNumber() {
  return this.userForm.get('mobileNumber');
} 
Now subscribe valueChanges of notificationMode property and set and clear validators as following.
handleFormChanges() {
   this.notificationMode.valueChanges.subscribe(
      mode => {
        if (mode==='email') {
           this.email.setValidators([Validators.required, Validators.email]);
           this.mobileNumber.clearValidators();
        } else if (mode === 'mobile') {
           this.mobileNumber.setValidators([Validators.required]);
           this.email.clearValidators();
        } else if (mode==='both') {
          this.email.setValidators([Validators.required, Validators.email]);
          this.mobileNumber.setValidators([Validators.required]);          
        }
        this.email.updateValueAndValidity();
        this.mobileNumber.updateValueAndValidity();
      }
   ); 
} 
2. Using expression that returns boolean

To perform conditional validations with formControlName, formControl and ngModel using built-in validators, we can use build-in validator Directives. For example if we write [required]="false" then required validation will not work and if we write [required]="true" then required validation will work. Find the code snippet to perform conditional validation in template-driven form.
<tr> 
   <td>Notification Mode: *</td>
   <td> 
     <input type="radio" value="email" name="notificationMode" required ngModel #mode="ngModel"> Email
     <input type="radio" value="mobile" name="notificationMode" required ngModel #mode="ngModel"> Mobile
     <input type="radio" value="both" name="notificationMode" required ngModel #mode="ngModel"> Both				
   </td>
</tr> 		 
<tr> 
   <td>Email: </td>
   <td> 
     <input name="email" [required]="mode.value === 'email' || mode.value === 'both'"
	[email]= "mode.value === 'email' || mode.value === 'both'" ngModel #uemail="ngModel">
				
	<div *ngIf="uemail.dirty && uemail.errors" class = "error"> 
           <div *ngIf="uemail.errors.required"> 
		Email required.
  	   </div>	
	   <div *ngIf="uemail.errors.email"> 
	        Email not valid.
 	   </div>	
	</div>
   </td>
</tr> 	 
<tr> 
   <td>Mobile Number: </td>
   <td> 
      <input name="mobileNumber" [required]="mode.value === 'mobile' || mode.value === 'both'" ngModel #mnumber="ngModel">
      <div *ngIf="mnumber.dirty && mnumber.errors" class = "error"> 
	<div *ngIf="mnumber.errors.required"> 
  	    Mobile number required.
        </div>			   
      </div>
   </td>
</tr> 

Example-1: Reactive Form Conditional Validation

Here we will provide complete code to perform reactive form conditional validation using valueChanges property and updateValueAndValidity() method for custom and built-in validators.
reactive-form.component.ts
import { Component, OnInit } from '@angular/core';
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
import { Observable } from 'rxjs';
import { User } from './user';
import { pwdMatchUsernameValidator } from './custom-validators/pwd-match-username-validator';
import { confirmPasswordValidator } from './custom-validators/confirm-password-validator';

@Component({
   selector: 'app-reactive-form',
   templateUrl: './reactive-form.component.html'
})
export class ReactiveFormComponent implements OnInit {
  userForm: FormGroup; 
  constructor(private formBuilder:FormBuilder) {
  }
  ngOnInit() {
    this.userForm = this.formBuilder.group({
      username: ['', [ Validators.required ]],
      password: ['', [ Validators.required ]],      
      confirmPassword: ['', [ Validators.required ]],          
      notificationMode: ['', [ Validators.required ]],       
      email: '',
      mobileNumber: ''
    });
    this.handleFormChanges();
  }
  handleFormChanges() {
    this.username.valueChanges.subscribe(
      uname => {
        this.password.setValidators([Validators.required, pwdMatchUsernameValidator(uname)]);
        this.password.updateValueAndValidity();
      }
    );
    this.password.valueChanges.subscribe(
      pwd => {
        const uname = this.username.value;
        this.password.setValidators([Validators.required, pwdMatchUsernameValidator(uname)]);

        this.confirmPassword.setValidators([Validators.required, confirmPasswordValidator(pwd)]);        
        this.confirmPassword.updateValueAndValidity();
      }
    );    
    this.confirmPassword.valueChanges.subscribe(
      () => {
        const pwd = this.password.value;
        this.confirmPassword.setValidators([Validators.required, confirmPasswordValidator(pwd)]);
      }
    );     
    this.notificationMode.valueChanges.subscribe(
      mode => {
        if (mode==='email') {
           this.email.setValidators([Validators.required, Validators.email]);
           this.mobileNumber.clearValidators();
        } else if (mode === 'mobile') {
           this.mobileNumber.setValidators([Validators.required]);
           this.email.clearValidators();
        } else if (mode==='both') {
          this.email.setValidators([Validators.required, Validators.email]);
          this.mobileNumber.setValidators([Validators.required]);          
        }
        this.email.updateValueAndValidity();
        this.mobileNumber.updateValueAndValidity();
      }
    ); 
  }
  onFormSubmit() {
    let user: User = this.userForm.value;
    console.log(user);
    this.userForm.reset();
  }
  get username() {
    return this.userForm.get('username');
  }
  get password() {
    return this.userForm.get('password');
  }  
  get confirmPassword() {
    return this.userForm.get('confirmPassword');
  }   
  get notificationMode() {
    return this.userForm.get('notificationMode');
  }        
  get email() {
    return this.userForm.get('email');
  }  
  get mobileNumber() {
    return this.userForm.get('mobileNumber');
  }   
} 
reactive-form.component.html
<h3>Reactive User Form</h3>
<form [formGroup]="userForm" (ngSubmit)="onFormSubmit()">
 <table>
   <tr>
      <td>Username: *</td>
      <td>
         <input formControlName="username">
         <div *ngIf="username.dirty && username.errors" class = "error">
            <div *ngIf="username.errors.required"> 
               Username required.
            </div>
         </div>
      </td>
   </tr>
   <tr>
      <td>Password: *</td>
      <td>
         <input formControlName="password" type="password">
         <div *ngIf="password.dirty && password.errors" class = "error">
            <div *ngIf="password.errors.required"> 
               Password required.
            </div>
            <div *ngIf="password.errors.matchForUsername"> 
               Password cannot be same as Username.
            </div>
         </div>
      </td>
   </tr>
   <tr>
      <td>Confirm Password: *</td>
      <td>
         <input formControlName="confirmPassword" type="password">
         <div *ngIf="confirmPassword.dirty && confirmPassword.errors" class = "error">
            <div *ngIf="confirmPassword.errors.required"> 
               Confirm Password required.
            </div>
            <div *ngIf="confirmPassword.errors.cnfPassword"> 
               Confirm Password not matched.
            </div>
         </div>
      </td>
   </tr>
   <tr>
      <td>Notification Mode: *</td>
      <td>
         <input type="radio" value="email" formControlName="notificationMode"> Email
         <input type="radio" value="mobile" formControlName="notificationMode"> Mobile
         <input type="radio" value="both" formControlName="notificationMode"> Both
      </td>
   </tr>
   <tr>
      <td>Email: </td>
      <td>
         <input formControlName="email">
         <div *ngIf="email.dirty && email.errors" class = "error">
            <div *ngIf="email.errors.required"> 
               Email required.
            </div>
            <div *ngIf="email.errors.email"> 
               Email not valid.
            </div>
         </div>
      </td>
   </tr>
   <tr>
      <td>Mobile Number: </td>
      <td>
         <input formControlName="mobileNumber">
         <div *ngIf="mobileNumber.dirty && mobileNumber.errors" class = "error">
            <div *ngIf="mobileNumber.errors.required"> 
               Mobile number required.
            </div>
         </div>
      </td>
   </tr>
   <tr>
      <td colspan="2">
         <button [disabled]="userForm.invalid">Submit</button>
      </td>
   </tr>
 </table>
</form> 
user.ts
export class User {
    username: string;
    password: string;    
    notificationMode: string;
    email: string;
    mobileNumber: string;
} 

Example-2: Template-Driven Form Conditional Validation

Here we will provide complete code to perform template-driven form conditional validation using custom and built-in validator Directive. We have already created our custom validator Directive above in the article for conditional validation for username and password and confirm password i.e. matchForUsername and cnfPassword. Here we will use them. Find the complete template-driven user form code.
template-driven-form.component.ts
import { Component, OnInit } from '@angular/core';
import { NgForm } from '@angular/forms';
import { User } from './user';
import { Observable } from 'rxjs';

@Component({
   selector: 'app-template-form',
   templateUrl: './template-driven-form.component.html'
})
export class TemplateDrivenFormComponent implements OnInit {
  constructor() {
  }
  ngOnInit() {
  }
  onFormSubmit(form: NgForm) {
     let user: User = form.value;
     console.log(user);
     form.resetForm();
  }
} 
template-driven-form.component.html
<h3>Template-driven User Form</h3>
<form #userForm="ngForm" (ngSubmit)="onFormSubmit(userForm)">
 <table>
   <tr>
      <td>Username: *</td>
      <td>
         <input name="username" required ngModel #uname="ngModel">
         <div *ngIf="uname.dirty && uname.errors" class = "error">
            <div *ngIf="uname.errors.required"> 
               Username required.
            </div>
         </div>
      </td>
   </tr>
   <tr>
      <td>Password: *</td>
      <td>
         <input type="password" name="password" required [matchForUsername]="uname.value" ngModel #pwd="ngModel">
         <div *ngIf="pwd.dirty && pwd.errors" class = "error">
            <div *ngIf="pwd.errors.required"> 
               Password required.
            </div>
            <div *ngIf="pwd.errors.matchForUsername"> 
               Password cannot be same as Username.
            </div>
         </div>
      </td>
   </tr>
   <tr>
      <td>Confirm Password: *</td>
      <td>
         <input type="password" name="confirmPassword" required [cnfPassword]="pwd.value" ngModel #cnfPwd="ngModel">
         <div *ngIf="cnfPwd.dirty && cnfPwd.errors" class = "error">
            <div *ngIf="cnfPwd.errors.required"> 
               Confirm Password required.
            </div>
            <div *ngIf="cnfPwd.errors.cnfPassword"> 
               Confirm Password not matched.
            </div>
         </div>
      </td>
   </tr>
   <tr>
      <td>Notification Mode: *</td>
      <td> 
         <input type="radio" value="email" name="notificationMode" required ngModel #mode="ngModel"> Email
         <input type="radio" value="mobile" name="notificationMode" required ngModel #mode="ngModel"> Mobile
         <input type="radio" value="both" name="notificationMode" required ngModel #mode="ngModel"> Both				
      </td>
   </tr>
   <tr>
      <td>Email: </td>
      <td>
         <input name="email" [required]="mode.value === 'email' || mode.value === 'both'"
         [email]= "mode.value === 'email' || mode.value === 'both'" ngModel #uemail="ngModel">
         <div *ngIf="uemail.dirty && uemail.errors" class = "error">
            <div *ngIf="uemail.errors.required"> 
               Email required.
            </div>
            <div *ngIf="uemail.errors.email"> 
               Email not valid.
            </div>
         </div>
      </td>
   </tr>
   <tr>
      <td>Mobile Number: </td>
      <td>
         <input name="mobileNumber" [required]="mode.value === 'mobile' || mode.value === 'both'" ngModel #mnumber="ngModel">
         <div *ngIf="mnumber.dirty && mnumber.errors" class = "error">
            <div *ngIf="mnumber.errors.required"> 
               Mobile number required.
            </div>
         </div>
      </td>
   </tr>
   <tr>
      <td colspan="2">
         <button [disabled]="userForm.invalid">Submit</button>
      </td>
   </tr>
 </table>
</form> 
app.component.ts
import { Component } from '@angular/core';

@Component({
   selector: 'app-root',
   template: `
        <app-reactive-form></app-reactive-form>
        <app-template-form></app-template-form>
    `
})
export class AppComponent {
} 
app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { AppComponent } from './app.component';
import { ReactiveFormComponent } from './reactive-form.component';
import { TemplateDrivenFormComponent } from './template-driven-form.component';
import { PwdMatchUsernameValidatorDirective } from './custom-validators/pwd-match-username-validator';
import { ConfirmPasswordValidatorDirective } from './custom-validators/confirm-password-validator';

@NgModule({
  imports: [
      BrowserModule,
      ReactiveFormsModule,
      FormsModule
  ],
  declarations: [
      AppComponent,
      ReactiveFormComponent,
      TemplateDrivenFormComponent,
      PwdMatchUsernameValidatorDirective,
      ConfirmPasswordValidatorDirective
  ],
  providers: [
  ],
  bootstrap: [
      AppComponent
  ]
})
export class AppModule { } 
styles.css
table {
    border-collapse: collapse;
}
table, th, td {
    border: 1px solid black;
}
.error {
    color: red;
}
.success {
    color: green;
} 

Run Application

To run the application, find the steps.
1. Download source code using download link given below on this page.
2. Use downloaded src in your Angular CLI application. To install Angular CLI, find the link.
3. Run ng serve using command prompt.
4. Access the URL http://localhost:4200
Enter the data into user form and if form is not validated, we will get error messages. Find the print screen.
Angular Conditional Validation

References

Angular Doc: valueChanges
Angular Doc: updateValueAndValidity()
Angular Doc: registerOnValidatorChange()
Angular valueChanges and statusChanges

Download Source Code

POSTED BY
ARVIND RAI
ARVIND RAI
FIND MORE TUTORILAS


©2018 concretepage.com | Privacy Policy | Contact Us