Kunal Vijan
Kunal Vijan

Reputation: 447

Batch operations on restapi from angular

I wanted to do the bulk operations on my JSON from angular using httpclient. But when I am doing it it's unable to update the JSON rather it's only updating the last checked record.

Need your support to fix the code.

I think I need to write a bulk operation in services similar to updateUser carrying multiple records and post to service.

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';

@Injectable({
  providedIn: 'root'
})

export class CommonService {

  constructor(private http:HttpClient) { }

  createUser(user: any) {
    return this.http.post("http://localhost:3000/users", user);
  }

  getAllUser() {
    return this.http.get("http://localhost:3000/users");
  }

  updateUser(user: any): Observable<any> {
    return this.http.put("http://localhost:3000/users/" + user.id, user);
  }

  deleteUser(user: any) {
    return this.http.delete("http://localhost:3000/users/" + user.id);
  }

}

app.component.ts

import { Component } from '@angular/core';
import { CommonService } from './common.service';
import { NgForm } from '@angular/forms';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})

export class AppComponent {
  title = 'db-poc1';
  allUser: any;
  isEdit = false;
  isView = false;
  isBatchEdit = false;
  totalRecords: any;
  page: Number = 1;
  currentImpact: string = '';

  userObj = {
    id: '', first_name: '', last_name: '', email: '', gender: '', ip_address: '', impact: ''
  }

  impactCount = {
    applicable: 0, notapplicable: 0, fyi: 0 
  }

  batchUpdateUsers = [];

  constructor(private commonService: CommonService) {}

  ngOnInit() {
    this.getLatestUser();
  }
  
  checkboxClicked() {
    this.batchUpdateUsers = this.allUser.filter(row => row.checked);
    this.isView  = false;
    this.isBatchEdit = this.batchUpdateUsers.length > 0;
    this.currentImpact = this.userObj.impact;
  }

  addUser(formObj: any) {
    this.commonService.createUser(formObj).subscribe((response) => {
      this.getLatestUser();
    })
  }

  getLatestUser() {
    this.commonService.getAllUser().subscribe((response) => {
      this.allUser = response;
      this.totalRecords = this.allUser.length;
      this.getApplicableCounts();
      this.allUser.forEach(row => row.checked = false);
    })
  }

  getApplicableCounts() {
    this.impactCount = {applicable: 0,notapplicable: 0,fyi: 0}
    this.allUser.forEach(row => {
      if (row.impact === 'Applicable') {
        this.impactCount.applicable++;
      } else if (row.impact === 'Not Applicable') {
         this.impactCount.notapplicable++;
      } else if (row.impact === 'FYI') {
        this.impactCount.fyi++;
      }
    });
  }

  editUser(user: any) {
    this.isEdit = true;
    this.userObj = user;
    this.allUser.forEach(user => user.checked = false);
    this.currentImpact = user.impact;
  }

  deleteUser(user: any) {
    this.commonService.deleteUser(user).subscribe(() => {      
      this.getLatestUser();
    })
  }

  updateUser() {
    this.isEdit = !this.isEdit;
    this.userObj.impact = this.currentImpact;
    this.commonService.updateUser(this.userObj).subscribe(() => {
      this.getLatestUser();
    })
    this.getApplicableCounts();
  }

  cancelEdit() {
    this.isEdit = false;
    this.isView = false;
  }

  viewUser(user: any) {
    this.isView = true;
    this.userObj = user;
  }

  cancelBatchEdit() {
    this.isBatchEdit = false;
    this.allUser.forEach(user => {user.checked = false});
  }

  batchUpdateUser() {
    this.isBatchEdit = false;
    const batchUpdateUserList = [];
    this.allUser.forEach(user => {
      if (user.checked) {
        user.impact = this.currentImpact
        batchUpdateUserList.push(user);
        user.checked = false;
      }
    });

    this.commonService.updateUser(this.userObj).subscribe(() => {
      this.getLatestUser();
    })

    this.getApplicableCounts();
  }

}

app.component.html

<div class="container-fluid">
    <div class="text-right toal-records">Total: {{totalRecords}}</div>
      <div style="padding-left: 20px">
        Male: {{genderCount.male}} 
        Female: {{genderCount.female}}
        Other: {{genderCount.other}}</div>
      <div style="padding-left: 20px">
        Applicable: {{impactCount.applicable}}
        Not Applicable: {{impactCount.notApplicable}}
        FYI: {{impactCount.fyi}}
      </div>
      <table class="table table-sm table-responsive">
        <thead>
          <tr>
            <th *ngIf="!isEdit">Edit</th>
            <th>First Name</th>
            <th>Last Name</th>
            <th>Email</th>
            <th>Gender</th>
            <th>ID Address</th>
    <th>Impact</th>  
    <th></th>
  </tr>
</thead>
<tbody>
  <tr class="record-row" (click)="viewUser(user)" *ngFor="let user of allUser">
    <input *ngIf="!isEdit" [(ngModel)]="user.checked" type="checkbox" (change)="checkboxClicked()">
    <td>{{user.first_name}}</td>
    <td>{{user.last_name}}</td>
    <td>{{user.email}}</td>
    <td>{{user.gender}}</td>
    <td>{{user.ip_address}}</td>
    <td>{{user.impact}}</td>
    <td>
      <button *ngIf="!isEdit" class="btn btn-primary btn-sm" (click)="editUser(user)" data-toggle="modal" data-target="#exampleModel">Edit</button>
    </td>
  </tr>
</tbody>
</table>

<div *ngIf="isView" class="view-details">
  <ul>
    <li>First Name: {{userObj.first_name}}</li>
    <li>Last Name: {{userObj.last_name}}</li>
    <li>Email: {{userObj.email}}</li>
    <li>Gender: {{userObj.gender}}</li>
    <li>IP Address: {{userObj.ip_address}}</li>
    <li>Impact: {{userObj.impact}}</li>
  </ul>
</div>

<div *ngIf="isBatchEdit && !isEdit">    
<form #myForm="ngForm">
      <div class="form-group">
    <select name="impact" class="form-control form-control-sm" [(ngModel)]="currentImpact">
      <option>Applicable</option>
      <option>Not Applicable</option>
      <option>FYI</option>
    </select>
  </div>
  <button type="button" (click)="batchUpdateUser()" class="btn btn-success btn-sm btn-update mr-2">
    Update
    </button>
  <button type="button" (click)="cancelBatchEdit()" class="btn btn-secondary btn-sm">Cancel</button>
</form>        
  </div>

<div *ngIf="isEdit">    
<form #myForm="ngForm">
      <div class="form-group">
    <select name="impact" class="form-control form-control-sm" [(ngModel)]="currentImpact">
      <option>Applicable</option>
      <option>Not Applicable</option>
      <option>FYI</option>
    </select>
  </div>
  <button type="button" (click)="updateUser()" class="btn btn-success btn-sm btn-update mr-2" >Update</button>
  <button type="button" (click)="cancelEdit()" class="btn btn-secondary btn-sm">Cancel</button>
</form>        
  </div>
</div>

https://stackblitz.com/edit/angular-ivy-bsrwmh?file=src/app/app.component.html

Upvotes: 0

Views: 1194

Answers (1)

Fasid Mpm
Fasid Mpm

Reputation: 557

IIUC, you need to batch user updates. which confirms that in the API side there must be a way to update multiple users at once. with that assumption here is my answer.

You can add this method in commonService and just pass in the list of total users that you want update.


  batchUpdateUsers(users: any[], batchSize = 10): Observable<void> {
    const batches = [];
    let offset = 0;
    while (offset < users.length) {
      batches.push(
        users.slice(offset, offset + batchSize)
      );
      offset += batchSize;
    }
    return forkJoin(
      batches.map(batch => this.http.put("http://localhost:3000/batchUserUpdate", batch))
    );
  }

Note: /batchUserUpdate , there must be some kind of API that accepts multiple user updates.

If in case you dont have such a batchUserUpdate api, you can replace the return statement with the following,

return forkJoin(
  users.map(user => this.updateUser(user))
);

Upvotes: 1

Related Questions