Search code examples
angularngrxngxs

Angular Form array duplicate fields issue


I have two issues:

1) Same value is displayed in all select boxes 2) On click of add, two select boxes are added, I want only one to be added

I have uploaded a demo on https://stackblitz.com/edit/angular-ngxs-select-form-solved


Solution

  • https://stackblitz.com/edit/angular-ngxs-select-form-solved-rnz3hz try this.

    You have to add value to the formControl instead of ngModel, the value from ngModel won't be reflected in bindings where formControlName is used.

    Use bindings for formControlName in dynamically generated inputs:

    <div formArrayName="userTechnologies">
        <!-- loop throught units -->
        <div *ngFor="let unit of form['controls'].userTechnologies['controls']; let i = index ">
            <!-- row divider show for every nex row exclude if first row -->
            <div *ngIf="form['controls'].userTechnologies['controls'].length > 1 && i > 0">
                <hr>
            </div>
            <div [formGroupName]="i">
                <div class="form-group">
                    <label>Technologies</label>
                    <select class="form-control" formControlName="user_technology">
                        <option value="">Select Technology</option>
                        <option *ngFor="let technology of technologies | async" [value]="technology.id">
               {{technology.name}}
            </option>
                    </select>
                    <div *ngIf="unit['controls'].user_technology.invalid" class="alert alert-danger">
                        <div *ngIf="unit['controls'].user_technology.errors.required">
                            Technology is required.
                        </div>
                    </div>
                </div>
                <button class="btn btn-danger" *ngIf="form['controls'].userTechnologies['controls'].length > 1" (click)="removeTechnology(i)">Delete</button>
            </div>
        </div>
        <button class="btn btn-primary" (click)="addTechnology()">Add</button>
    </div>
    

    In your .ts, addTechnology should work for both new input and for dynamically generated input for setting its value

      addTechnology(tech = '') {  //<--Edited this
        const control = <FormArray>this.form.controls['userTechnologies'];
        control.push(this.getTechnology(tech));  //<--Edited this
        this.editname = ''; //<--Added this
        this.form.controls.userTechnologies.updateValueAndValidity(); //<--Added this
      }
    
      getTechnology(tech = '') {
        return this.fb.group({
          user_technology: [tech, Validators.required] //<--Edited this
        });
      }
    

    And while assigning the value, call addTechnology for generating dynamic controls:

      showUser(id) {
        this.editdetails$ = this.store.select(UserState.userByIndex)
          .pipe(map(filterFn => filterFn(id)));
    
        this.editdetails$.subscribe(response => {
          this.edituserarray = [];
          this.editid = response.id;
          this.editname = response.name;
          var technologies = response.technology.split(',');
          for (let tech of technologies) {
            let newName = {
              techno: tech
            };
            // this.edituserarray.push(newName); //<--- Commented this
            this.addTechnology(tech); //<--- Added this
          }
        })
      }