Tips for validating duplicate entries in dynamically added form fields

I have a form called verification form and a form array named RepDetails with three fields. Initially, the form displays three fields, but users can add more details by clicking on "add more". I need assistance in ensuring that Mydetails[0].name is not identical to mydetails[1].name. Can anyone provide guidance on this issue?

Myform = this.fb.group({   
    Mydetails: this.fb.array([this.createMydetails()])   
  });

createMydetails(): FormGroup {
    return this.fb.group({
      Myname: ['', Validators.required ],
      Myid: ['', Validators.required],
      Myphone: ['', Validators.required]
    });
  }

Html

<div
        formArrayName="Mydetails"
        *ngFor="let item of Mydetails.controls; let i = index"
      >
        <div [formGroupName]="i">
          <mat-form-field appearance="outline">
            <mat-label class="required">
              Name
            </mat-label>
            <input
              appAlphaNumeric
              [maxlength]="maxRepNamelen"
              formControlName="Myname"
              class="mat-body-1"
              matInput
            />
          </mat-form-field>
          <mat-form-field appearance="outline">
            <mat-label class="required">
              Id
            </mat-label>
            <input
              appAlphaNumeric
            
              formControlName="Myid"
              class="mat-body-1"
              matInput
            />
          </mat-form-field>
          <div class="phn-wrapper">
            <ngx-intl-tel-input
              [cssClass]="'int-phn'"
              [searchCountryField]="[
                SearchCountryField.Iso2,
                SearchCountryField.Name
              ]"name="phone"
              formControlName="Myphone"
            >
            </ngx-intl-tel-input>
          </div>
          <mat-icon
            *ngIf="Mydetails.length > 1"
            (click)="remove(i)"
            class="close"
            >close</mat-icon
          >
          
        </div>
      </div>
        class="add-fields"
        (click)="add()"
      >
        <mat-icon class="icon">add_circle_outline</mat-icon>
        <span class="text mat-button">
          {{"ADD MORE"}}</span
        >
      </div>

Answer №1

In this SO you have implemented a custom validation for a FormArray. The issue with using a custom validation on a formArray is that it gets triggered whenever any value in the formArray is changed (whether it's repName, passport, or phoneName).

You can create a custom validator for a Form Control that considers other controls as well.

  checkIfUnique(index) {
    return (control: FormControl) => {
      // Try to get the form array
      // control.parent is the FormGroup, control.parent.parent is the FormArray
      const formArray =
        control.parent && control.parent.parent
          ? (control.parent.parent as FormArray)
          : null;
      if (formArray && formArray.controls.length) {
        for (let i = index - 1; i >= 0; i--) {
          if (
            (formArray.at(i) as FormGroup).get("repName").value == control.value
          )
            return { errorRepeat: true };
        }
      }
    };
  }

When creating the formGroup of the formArray, make sure to pass the "index" of the element to the validator. Therefore, you need to modify your createRep function accordingly.

// Pass the index
createRep(index:number): FormGroup {
    return this.fb.group({
      repName: ['', [Validators.required,this.checkIfUnique(index) ]],
      passport: ['', Validators.required],
      phoneNumber: ['', Validators.required]
    });
  }

Lastly, when changing the value of any 'repName', ensure to validate the rest of the controls. Angular only checks the formControl that has been changed, not the others. So we create a function for this purpose:

  checkFormArray()
  {
    this.detailsFormArray.controls.forEach(x=>{
      (x as FormGroup).get('repName').updateValueAndValidity()
    })
  }
  //I use a getter for the formArray
  get detailsFormArray() {
     return (this.verificationForm.get("repDetails") as FormArray)
  }

Invoke the function within the input tag like so:

  <input formControlName="repName" (input)="checkFormArray()">

You can view the actual implementation on StackBlitz

NOTE: I removed the angularjs tag from your question as it pertains solely to Angular.

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

Access to Oracle Cloud exclusive to Angular Framework, omitting AngularJS and Mid-Tier

Exploring Oracle Cloud for the first time and embarking on a self-learning journey, I have developed an Angular application (not AngularJS) where I aim to upload images into my Oracle Cloud Object Storage Bucket. My goal is to accomplish this using only An ...

Angular 12 experiencing CSS alignment issues

In my Angular component, I have the following CSS: .folders { border-left: 5px solid #b8744f; -moz-border-radius: 5px; -webkit-border-radius: 5px; -moz-box-shadow: inset 0 0 1px #fff; -webkit-box-shadow: inset 0 0 1px #fff; /*CORRECTION NEEDED ...

Ways to make an element disappear when clicking outside of it in Angular 7 or with CSS

After entering text into an input field and pressing the space key, a div called 'showit' will be displayed. However, I want this div to hide when clicking outside of it. See the code below for reference: home.component.html <input type="tex ...

If I exclusively utilize TypeScript with Node, is it possible to transpile it to ES6?

I am developing a new Node-based App where browser-compatibility is not a concern as it will only run on a Node-server. The code-base I am working with is in TypeScript. Within my tsconfig.json, I have set the following options for the compiler: { "inc ...

Steps for logging in using Spring Boot and Angular 2

My Front End application is built with Angular 2 and runs on http:// localhost:5555. Meanwhile, my Back End application uses Spring Boot and runs on http://localhost:8080/. It provides a REST API for my Angular 2 application. Sending requests from http:/ ...

Retrieving a FirebaseObjectObservable child in Angularfire2 is straightforward

Can you target a specific child of a FirebaseObjectObservable in Angular? Take a look at RcTestAppComponent.save() function below for commented lines. Here is an example: https://github.com/angular/angularfire2/blob/master/docs/3-retrieving-data-as-lists. ...

Using React's Ref to handle conditional rendering and handling the case when

I am facing an issue with my React ref animationRef being null when I conditionally render an element. It works perfectly fine outside of the condition, but not within it. Is there a way to ensure that the ref has a value even when conditionally renderin ...

Displaying rows with no data in an Angular Material table

Currently facing an issue while integrating Angular's material table in a new project. The data is not being displayed, only empty rows are visible. Surprisingly, the same logic works perfectly fine in another project. I have spent a considerable amou ...

The npm audit command flagged an issue with an invalid tag name,

Whenever I run npm audit on a directory containing the project's package.json and package-lock.json, I encounter the following error message: 0 info it worked if it ends with ok 1 verbose cli [ '/home/user/Downloads/node-v10.14.0-linux-x64/bin/n ...

Aliases for NPM packages and TypeScript declaration files

I am in need of two separate versions of a package, and fortunately with npm 6.9.0 I can easily accomplish that now. My dilemma is this: the package comes with type definitions. However, when I create an alias for this package and refer to it using the al ...

NextJS function utilizes its own references within React and automatically fetches data without the need for an import

I recently purchased this template and I'm trying to figure out which page the code snippet "{getLayout(<Component {...pageProps} />)}" is directed to during the initial load. It seems like it might be a global variable hidden somewher ...

Router-outlet not displaying any content

I'm encountering an issue with using routing inside mat-drawer. Strangely, it results in a blank page. However, when I comment out the router-outlet element, the page displays correctly. Does anyone have insight on why this is happening? P.S. When I ...

Leverage the power of forkJoin in JavaScript by utilizing objects or sourcesObject

I'm currently facing an issue with my code snippet below: getInformations().subscribe( informations => { let subs = []; for (const information of informations) { subs.push(getOtherDetails(information.id)); } ...

Error is being thrown due to defining a variable after it has already been declared and

Before I use a variable, I encountered the issue of using it before its definition, interface IProps extends WithStyles<typeof STYLES>; const STYLES = () => ({ }) Although it didn't cause any errors, a warning appeared: STYLES used befo ...

Is there a way to reset useQuery cache from a different component?

I am facing an issue with my parent component attempting to invalidate the query cache of a child component: const Child = () => { const { data } = useQuery('queryKey', () => fetch('something')) return <Text>{data}& ...

Struggling to resolve Docker freezing during the "RUN npm run build" step while working with Angular 15?

I am facing an issue while attempting to create a Dockerized Angular 15 project. The build process always seems to hang at the RUN npm run build step and never finishes. This is a fresh installation using ng new ng-sandbox-15, with the Dockerfile, .dockeri ...

What could be the reason for my Angular website displaying a directory instead of the expected content when deployed on I

My current challenge involves publishing an Angular application to a Windows server through IIS. Upon opening the site, instead of displaying the actual content, it shows a directory. However, when I manually click on index.html, the site appears as intend ...

Issue: Inadequate parameters have been supplied for the localized pathname (getPathname()). This problem arose after the inclusion of "next-intl/routing" module

After implementing the config file and replacing : Navigation File import { createLocalizedPathnamesNavigation, Pathnames } from 'next-intl/navigation'; With : Config File import {Pathnames, LocalePrefix} from 'next-intl/routing';} ...

Securing Single Page Applications

Have you ever wondered how SPA ensure the security of their sites? With all the embedded scripts, it seems like anyone could access and analyze the code. Do you have any thoughts on this? Additionally, when connecting to other web services that require sp ...

When transitioning from Angular5 to Angular6, it seems that the angular.json file has not been properly updated

I am looking to transition from Angular5 to Angular6, following the guidance provided in this answer My attempt to update .angular-cli.json to angular.json using three commands did not yield the expected results: npm install -g @angular/cli npm install @ ...