DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

The software you build is only as secure as the code that powers it. Learn how malicious code creeps into your software supply chain.

Apache Cassandra combines the benefits of major NoSQL databases to support data management needs not covered by traditional RDBMS vendors.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Related

  • The Most Popular Angular UI Libraries To Try in 2021
  • Create a Beautiful Login Form With Angular Material
  • Exploring Intercooler.js: Simplify AJAX With HTML Attributes
  • Dynamic Web Forms In React For Enterprise Platforms

Trending

  • AWS to Azure Migration: A Cloudy Journey of Challenges and Triumphs
  • Developers Beware: Slopsquatting and Vibe Coding Can Increase Risk of AI-Powered Attacks
  • Infrastructure as Code (IaC) Beyond the Basics
  • The Full-Stack Developer's Blind Spot: Why Data Cleansing Shouldn't Be an Afterthought
  1. DZone
  2. Coding
  3. Frameworks
  4. Perform Conditional Validation With the valueChanges Method in Angular Reactive Forms

Perform Conditional Validation With the valueChanges Method in Angular Reactive Forms

In this post, we will learn to use Angular Reactive Form's value change detection and enable conditional validation on using this functionality.

By 
Dhananjay Kumar user avatar
Dhananjay Kumar
·
Mar. 19, 18 · Tutorial
Likes (4)
Comment
Save
Tweet
Share
92.7K Views

Join the DZone community and get the full member experience.

Join For Free

Learn How to Create Your First Angular Reactive Form here

Let's say you have a Reactive Form created using the FormBuilder class as shown below:

ngOnInit() {
    this.loginForm = this.fb.group({
      email: [null, Validators.required],
      password: [null, [Validators.required, Validators.maxLength(8)]],
      phonenumber: [null]
    });

  }

You have created loginForm, which has three controls: email, password, and phone number. Here, you are using FormBuilder to create a reactive form. On the component template, you can attach loginForm as shown in the code below. Using property binding, the formGroup property of the HTML form element is set to loginForm and the formControlName value of these controls are set to the individual FormControl property of FormBuilder.

<form (ngSubmit)='loginUser()' [formGroup]='loginForm' novalidate class="form">
     <input formControlName='email' type="text" class="form-control" placeholder="Enter Email" />
     <div class="alert  alert-danger" *ngIf="loginForm.get('email').hasError('required') && loginForm.get('email').touched">
         Email is required
     </div>
     <input formControlName='password' type="password" class="form-control" placeholder="Enter Password" />
     <input formControlName='phonenumber' type="text" class="form-control" placeholder="Enter Phone Number" />
     <div class="alert  alert-danger" *ngIf="loginForm.get('phonenumber').hasError('required') && loginForm.get('phonenumber').touched">
         Phone Number is required
     </div>
     <br />
     <button [disabled]='loginForm.invalid' class="btn btn-default">Login</button>
 </form>

We have also put error messages for email and phone number fields. Also, the submit button would only be enabled when the form is valid. Form submission is handled as shown in the listing below:

loginUser() {
    console.log(this.loginForm.status);
    console.log(this.loginForm.value);
}

If the form is valid in the browser console, you will get an output like below:

In addition, if there is an error, the submit button would be disabled and an error message will be shown as below:

Now assume a scenario that you have a radio button to send a notification. The user should able to select the send notification option, and, on basis of that, certain FormControls will have some validations.

Consider the form below:

We have added a Send Notification option. If the user selects Phone to send a notification, then the Phone Number field should be required, otherwise, it should not be. To achieve this, we need to perform following tasks:

  1. Listening to changes.
  2. Put conditional validation.

To start with, let us modify our form to handle the notification. So now the form has a notification FormControl with the default value set to null as shown in the listing below :

this.loginForm = this.fb.group({
    email: [null, Validators.required],
    password: [null, [Validators.required, Validators.maxLength(8)]],
    phonenumber: [null],
    notification: ['email']
});

On the Reactive form template, we will add a radio button group to handle the Send Notification option.

<form (ngSubmit)='loginUser()' [formGroup]='loginForm' novalidate class="form">
    <input formControlName='email' type="text" class="form-control" placeholder="Enter Email" />
    <div class="alert  alert-danger" *ngIf="loginForm.get('email').hasError('required') && loginForm.get('email').touched">
        Email is required
    </div>
    <input formControlName='password' type="password" class="form-control" placeholder="Enter Password" />
    <input formControlName='phonenumber' type="text" class="form-control" placeholder="Enter Phone Number" />
    <div class="alert  alert-danger" *ngIf="loginForm.get('phonenumber').hasError('required') && loginForm.get('phonenumber').touched">
        Phone Number is required
    </div>
    <br />
    <label class='control-label'>Send Notification</label>
    <br />
    <label class="radio-inline">
        <input type="radio" value="email" formControlName="notification">Email
    </label>
    <label class="radio-inline">
        <input type="radio" value="phone" formControlName="notification">Phone
    </label>

    <br />
    <button [disabled]='loginForm.invalid' class="btn btn-default">Login</button>
</form>

At this point form, this looks like below:

Subscribe to valueChanges

In Reactive forms, both FormControls and FormGroups has a valueChanges method. It returns an observable type, so you can subscribe to it, to work with real-time value changing of FormControls or FormGroups.

In our example, we need to subscribe to the valueChanges method of the notification for FormControl. This can be done as below:

formControlValueChanged() {
    this.loginForm.get('notification').valueChanges.subscribe(
        (mode: string) => {
            console.log(mode);
        });
}

We need to call this using an OnInit lifecycle hook a shown below:

ngOnInit() {
    this.loginForm = this.fb.group({
        email: [null, Validators.required],
        password: [null, [Validators.required, Validators.maxLength(8)]],
        phonenumber: [null],
        notification: ['email']
    });

    this.formControlValueChanged();

}

Now when you change the selection for the notification on the form in the browser console you can see that you have the most recent value.

Keep in mind that we are not handling any event on the radio button to get the latest value. Angular has a valueChanges method which returns recent values as observables on the FormControl and FormGroup, and we are subscribed to that for the recent value on the notification FormControl.

Conditional Validation

Our requirement is that when notification is set to phone then the phonenumber FormControl should be a required field and if it is set to email then phonenumber FormControl should not have any validation.

Let us modify the formControlValueChnaged() function as shown in the next listing to enable conditional validation on the phonenumber FormControl.

formControlValueChanged() {

    const phoneControl = this.loginForm.get('phonenumber');
    this.loginForm.get('notification').valueChanges.subscribe(
        (mode: string) => {
            console.log(mode);
            if (mode === 'phone') {
                phoneControl.setValidators([Validators.required]);
            }
            else if (mode === 'email') {
                phoneControl.clearValidators();
            }
            phoneControl.updateValueAndValidity();
        });

}

There is a lot of code above, so let's walk through it line by line.

  1. Using the get method of FormBuilder, we get an instance of the phone number FormControl.
  2. We then subscribe to the valueChanges method of the notification FormControl.
  3. Check the current value of the notification FormControl
  4. If the current value is phone, using the setValidators method of FormControl to set the required validator on the phonenumber control.
  5. If the current value is email, using the clearValidators method of FormControl we clear all validations on the phonenumber control.
  6. Lastly, we call the updateValueAndValidity method to update the validation rules of phonecontrol.

Run the application and you will see that as you change notification values, the validation of phonenumber is getting changed:

By using the power of Angular Reactive Form's valueChanges method, you can achieve conditional validations and many other functionalities, such as reacting to changes in the underlying data model of the reactive form.

Form (document) AngularJS

Published at DZone with permission of Dhananjay Kumar, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • The Most Popular Angular UI Libraries To Try in 2021
  • Create a Beautiful Login Form With Angular Material
  • Exploring Intercooler.js: Simplify AJAX With HTML Attributes
  • Dynamic Web Forms In React For Enterprise Platforms

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!