Search code examples
angularbulkupdate

How to update multiple rows in the table? Angular 7


In my project there is popup which contain multiple values in loop.

Every row contains Enable button which convert text into text boxes and in the end of page there is a button name "Update".Then all the enable rows values are goes as a API parameter and then update al the rows. This below page have same functionality but this is in angular js. https://embed.plnkr.co/plunk/2Fue9L


Solution

  • A very simple formArray. As always we have a function that creates the formGroup and some auxiliary variables

      editing: number = -1; //<--here store the row we are editing
                            //typically we initialize the variable with "-1"
                            //to say that there are no rows selected
      formArray: FormArray = new FormArray([]); //<--our formArray, 
            //At first is empty, but NOT null, see =new FormArray([])
      oldValue: any; //<--here store the old values, this allows us
           //recover the data if we cancel the editing
    
    createGroup() {
        return new FormGroup({
          prop1: new FormControl(),
          prop2: new FormControl(),
          prop3: new FormControl()
        });
      }
    

    And a function to edit, cancel and add another row

    edit(index: number) {  //we pass the "index" of the row we want to edit
        this.editing = index;
        this.oldValue = {  //here store the actual value
                           //we using "spread operator"
                           //yes, we need a copy of the old values
          ...this.formArray.at(index).value
        };
      }
    
      cancel() {  //we using the oldValue to 
        this.formArray.at(this.editing).setValue(this.oldValue);
        this.editing=-1;  //and there are no row editing
      }
    
      add() //simple "push" a formGroup in our array
      {
        this.formArray.push(this.createGroup())
        //I say that, when add a new row we want beging to edit it
        this.edit(this.formArray.controls.length-1)
      }
    

    A simple (and very ugly .html)

    <button (click)="add()">Add</button>
    <form [formGroup]="formArray" (submit)="submit(formArray)">
      <table>
        <tr>
          <th>Prop1</th>
          <th>Prop2</th>
          <th>Prop3</th>
        </tr>
        <tbody>
         <!--we using ng-container to not create additional "tags"-->
         <!-- see how manage a formArray using let "group" of...
              and [formGroup]="group"
         -->
        <ng-container *ngFor="let group of formArray.controls;let i=index" [formGroup]="group">
           <!--when we are editing, show the inputs-->
            <tr *ngIf="editing==i"> 
          <th>
                <input formControlName="prop1">
          </th>
          <th>
                <input formControlName="prop2">
          </th>
          <th>
                <input formControlName="prop3">
          </th>
          <th>
                <button (click)="editing=-1">OK</button>
                <button (click)="cancel()">Cancel</button>
          </th>
            </tr>
           <!--when we are NOT editing, show the values-->
            <tr *ngIf="editing!=i">
          <td>
                {{group.get('prop1').value}}
          </td>
          <td>
                {{group.get('prop2').value}}
          </td>
          <td>
                {{group.get('prop3').value}}
          </td>
          <td>
                <button (click)="edit(i)">Edit</button>
                <button (click)="formArray.removeAt(i)">Delete</button>
          </td>
            </tr>
        </ng-container>
      </tbody>
      </table>
      <button>submit</button>
    </form>
    

    The function submit

    submit(formArray) {
        if (formArray.valid)
        {
           this.myService.saveData(formArray.value).  //(*)
              subscribe(res=>{
                 console.log(res)
              })
        }
        else 
           this.formArray.markAllAsTouched();
      }
    
    
    //(*)I has a service with a simple
    
    saveData(data:any[])
    {
        return this.httpClient.post("http://....",data)
    }
    

    And the stackblitz

    The API can be, if you're using .NET Core

    public class Data
    {
        string prop1 {get;set;}
        string prop2 {get;set;}
        string prop3 {get;set;}
    }
    
    [HttpPost), ActionName("UpdateBulk")]
    public async Task<object> UpdateBulk([FromBody]Data[]){
       try{
        ..you save your data here...
        return Ok(new { success = true, errorText = "Data saved!" });
       }
       catch(){
        return Ok(new { success = false, errorText = "Data incorrect" });
       }
    }