user21
user21

Reputation: 1351

Angular formControl - set a value in a particular row in the ngfor loop

Please refer to complete code here at stackblitz

When modify the first columnm dropdown to Model, it's observed that the 3rd column show list of models.

click on add row button --> for second row, modify the first column dropdown to System --> observed that the third column dropdown for the second row changed to system list too. However, it also modifies the third col of the other rows too . is there a way that I can modify only the third column of the second row ?

So the formControlName is the same in the ngFor loop, and I would like to watch the changes in the formControl and update the third column dropdown values only for that row (not all rows)

At stackblitz

Upvotes: 1

Views: 2168

Answers (1)

Eliseo
Eliseo

Reputation: 57971

You need use a FormArray. I suppose you want do some like

formArray:FormArray=new FormArray([this.newLine()]);

newLine() //This funcrion is WORNG, see update 2
{
   return this.formBuilder.group({
     onValues: [
        { value: "" },
        [Validators.required, Validators.pattern(/^[+-]?\d+(\.\d+)?$/)]
      ],
      ruleTypeValues: [{ value: "" }],
      getType: [{ value: "" }], 
      filterValue: [{ value: "" }]
   })
}
addLine()
{
   this.formArray.push(this.newLine())
}
removeLine(index)
{
   this.formArray.removeAt(index)
}

To manage, take the look over formArray.controls using [formGroup]

<form class="form" [formGroup]="formArray">
      <div *ngFor="let group of formArray.controls;let i=index" [formGroup]="group" class="rows">
        <div class="clr-select-wrapper">
          <select formControlName="getType">
            <ng-container *ngFor="let val of rootName">
              <option [ngValue]="val">{{ val }}</option>
            </ng-container>
          </select>
        </div>
        <div class="clr-select-wrapper">
          <select formControlName="ruleTypeValues">
            <ng-container *ngFor="let val of ruleType">
              <option [ngValue]="val">{{ val }}</option>
            </ng-container>
          </select>
        </div>
        <div class="clr-select-wrapper" *ngIf="getValues.length > 0">
          <select formControlName="onValues">
            <ng-container *ngFor="let val of getValues">
              <option [ngValue]="val">{{ val }}</option>
            </ng-container>
          </select>
        </div>
        <input
          *ngIf="getValues.length === 0"
          type="text"
          formControlName="filterValue"
          class="text"
          placeholder="sdf"
        />
        <div class="row-button">
          <button  (click)="addLine()">Add row</button>
          <button  (click)="removeLine(i)">Remove row </button>
          <button (click)="addBlock(row)">Add block</button>
        </div>
      </div>
    </form>

Update to subscribe to valueChanges of formGroup we need change the function newLine and make it in two steps:

newLine()
{
   const group=this.formBuilder.group({
     onValues: [
        { value: "" },
        [Validators.required, Validators.pattern(/^[+-]?\d+(\.\d+)?$/)]
      ],
      ruleTypeValues: [{ value: "" }],
      getType: [{ value: "" }], 
      filterValue: [{ value: "" }]
   })
   group.valuesChange.subscribe((res:any)=>{
     ..here the code
   }
   //or, if we only want to check, e.g. "getType"
   group.get('getType').valueChange.subscribe((res:any)=>{
      ..here the code
   }
   return group;
}

OR, after create the form, e.g. in ngOnInit

ngOnInit()
{
    this.formArray.valueChanges.subcribe((res:any)=>{
       ..here the code..
    }
}

Update2 the newLine function is wrong!!!

must be like

newLine(){
   const group=this.formBuilder.group({
     onValues: ["",
        [Validators.required, Validators.pattern(/^[+-]?\d+(\.\d+)?$/)]
      ],
      ruleTypeValues: [""],
      getType: [""], 
      filterValue: [""]
   })
   return group
}

Upvotes: 1

Related Questions