Validator in Angular FormControl ensures that two fields have the same value or both are empty

When filling out a form with four fields, I have encountered a specific requirement. Two of the fields are mandatory, which is straightforward. However, the other two must either both be empty or both have a value - essentially resembling an XNOR logic state.

s1_male     s1_female      s1_male_valid     s1_female_valid
empty       empty          true              true
value       empty          false             false
empty       value          false             false
value       value          true              true

Although the code below functions correctly, it does not update the UI appropriately. For example, if I input a value in 's1_male', it marks as invalid but 's1_female' remains unflagged. Even after entering a value in 's1_female', it still appears valid while 's1_male' is indicated as invalid. In such cases, I find myself going back to 's1_male' and either modifying or deleting the value to resolve the issue.

I attempted calling updateValueAndValidity() on both fields within the provided function, yet this action triggers an endless loop causing Chrome to eventually terminate.

formGroup.addControl('rx_male', new FormControl('', Validators.required));
formGroup.addControl('rx_female', new FormControl('', Validators.required));
formGroup.addControl('s1_male', new FormControl('', this.scaleOptionValidator(formGroup)));
formGroup.addControl('s1_female', new FormControl('', this.scaleOptionValidator(formGroup)));

// these line cause endless loop
formGroup.controls.s1_male.valueChanges.subscribe(value => {
  formGroup.controls.s1_female.updateValueAndValidity();
});
formGroup.controls.s1_female.valueChanges.subscribe(value => {
  formGroup.controls.s1_male.updateValueAndValidity();
});

...

private scaleOptionValidator(formGroup: FormGroup): ValidatorFn {
    return (control: AbstractControl): { [key: string]: boolean } | null => {
      let isValid = false;
      const female = formGroup.controls.s1_female;
      const male = formGroup.controls.s1_male;
      if (male && female) {

        if ((male.value && female.value) || (!male.value && !female.value)) {
          isValid = true;
        }

        return isValid ? null : { scalseNotValid: true };
      }
      return null;
    };
  }

Any suggestions would be greatly appreciated.

UPDATE: It seems that the formgroup approach is effective, however, I am also using Ionic here where, frustratingly, the ng-invalid class is applied but the ion-valid class overrides the UI styling until selecting and then deselecting the input field.

Answer №1

When faced with the task of validating two password fields in my sign up form, this was the solution I came up with.

validatePasswords(group: FormGroup): ValidationErrors | null {
    const password = group.get("password")
    const retypedPassword = group.get("retypedPassword")

    if (password !== null && retypedPassword !== null) {
        return password.value === retypedPassword.value ? null : { mismatch: true }
    } else {
        throw new Error("The form group is invalid. The group does not have a 'password' and/or a 'retypedPassword' control.")
    }
}

You can implement a similar method by creating an inner FormGroup for the passwords within your sign up form. Then, add a validator to that specific group and use its validity status to display error messages.


To streamline your code within the template, consider adding a getter function like this:

get passwords(): FormGroup {
    return this.signupForm.get("passwords") as FormGroup
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Navigating with Angular 2 router while authenticating with AngularFire2

Currently, I am working on a route where I need to wait for the auth object from Firebase before proceeding. Below is the code snippet that I have implemented: Route { path: 'random', component: RandomComponent, resolve: { auth: AuthServi ...

Retrieving the input value using ref in Vue 3 and TypeScript

It appears to be a straightforward issue, but I haven't been able to find consistent Vue 3 TypeScript documentation on accessing an input field and retrieving its value from within a function. <template> <Field type="text" ...

Tips for transferring a column in an array to an object field within an array

I have a piece of code where I need to pass values from the 'dataList' array into this.data object's 'labels' and 'datasets'-> data. When I try to directly set the values, I get an undefined result. So I created a var ...

How can Jest be configured to test for the "permission denied" error?

In my Jest test, I am testing the behavior when trying to start a node http server with an invalid path for the socket file: describe('On any platform', (): void => { it('throws an error when trying to start with an invalid socket P ...

Unlock the power of TypeScript's inheritance by utilizing static methods for type

In my TypeScript project, I have two classes: BaseModel and HotelModel. The HotelModel extends the BaseModel class, which provides static methods like findById, all, etc. export default class BaseModel { private collection:string _id:string | undefine ...

Is it necessary to manually unsubscribe from observables in the main Angular component?

I'm facing a dilemma with my Observable in the root Angular (6.x) component, AppComponent. Typically, I would unsubscribe from any open Subscription when calling destroy() using the lifecycle hook, ngOnDestroy. However, since the AppComponent serv ...

Utilizing Ionic 2 with Typescript for executing forEach operations

I am in the process of migrating my AngularJS application to Angular 2. In my AngularJS controller, I had a JSON array that I was iterating through to display data in an accordion list. Now, I need to implement the same functionality in my Angular 2 compon ...

Encountered an error while trying to generate the Component class for the ColorlibStepIcon from Material UI in TypeScript

I am trying to convert the ColorlibStepIcon functional component into a class component for my Stepper. Unfortunately, I have not been successful and keep encountering errors. I have attempted some changes but it is still not working as expected. You can ...

Using Angular to Make a Request for a Twitter API Access Token

I'm facing some challenges while trying to implement a Twitter Sign-In method for my angular app. The issue seems to be with the initial step itself. I am attempting to make a post request to the request_token API by following the steps outlined at th ...

Managing refresh events in Angular with F5 Key

Recently, I encountered an issue with my Angular project. During development (using ng s), everything functions normally and upon pressing F5, the page reloads correctly and works fine. However, when I build and deploy the project to a remote server, all ...

Is it advisable to blend Angular Material with Bootstrap?

I'm brand new to Angular Material and it seems to have its own intricate API. Coming from using Bootstrap, I'm accustomed to utilizing its grid system with classes like row, containers, cols, etc. I'm curious if it's considered a good o ...

Fullstack is unable to locate the specified Entity name model

I am encountering an issue with my fullstack web application built using Angular and Spring Boot. When attempting to call my userEntity in the Angular service class via localhost:8080, I receive an error stating "Cannot find name 'UserEnt ...

Unable to connect dynamic information in Angular 8 component

Error encountered during dynamic component loading DynamicBuilderComponent.ngfactory.js:198 ERROR Error: ExpressionChangedAfterItHasBeenCheckedError: The expression has changed after it was checked. Previous value: 'ng-pristine: true'. Current ...

What is the best way to perform unit testing on an Angular component that utilizes the Router?

While working in Angular 2.0.0, I encountered an issue when unit testing a component that utilizes Router. The error 'Supplied parameters do not match any signature of call target.' keeps appearing, with Visual Studio Code highlighting the new Ro ...

Encountered an error while attempting to install the DataTables npm package in an Angular

I am trying to add datatables to my angular application. Upon running ng add angular-datatables An error code is displayed (refer to the image). error image The cause of this error is unknown to me. Please review the package.json file as well. package.j ...

What do I do when I encounter the error message "Provider not found for RadioControlRegistry" in Angular 2? Which provider should

Which provider should be included in the provider component? <div class="radio"> <input let match id="male" type="radio" name="gender" value="true" [(ngModel)]="isMatching" (click)="isMatching(match.value)" > Take a look at my console output ...

Exploring properties of nested elements in React

Picture a scenario where a specific element returns: <Component1> <Component2 name="It's my name"/> </Component1> Now, what I want to accomplish is something like this: <Component1 some_property={getComponent2'sN ...

"Improve your Angular ngrx workflow by utilizing the sandbox pattern to steer clear of

Currently, I'm trying to determine whether my implementation of the ngrx and sandbox pattern is effective. Here's the issue I'm facing: getFiles(userId: number, companyId: number) { this.fileService.getFiles(userId, companyId).subscribe(re ...

"Exploring the world of Typescript code through the eyes of Chrome with the help of the

Currently, I am immersing myself in learning Angular2 by following along with this project: https://github.com/start-angular/angular2-node-socket-io-chat-app I am utilizing VS Code and the Debugger for Chrome. However, when attempting to debug the code an ...

Utilizing Angular for making API requests using double quotes

I am experiencing an issue with my service where the double quotation marks in my API URL are not displayed as they should be. Instead of displaying ".." around my values, it prints out like %22%27 when the API is called. How can I ensure that my ...