how to wait until deletion is complete then reload angular mat table

274 Views Asked by At

I have a mat table in my angular project just like below:

enter image description here

The data is fetched from server using rest API. The server side is using nodejs and sequelize. When I click the delete button, I want my mat table to refresh with new data. But unfortunately, the refresh data is loaded before the delete is completed, so it looks as if the delete button is not functioning.

Here is my code:

list.component.ts

import {AfterViewInit, ChangeDetectorRef, Component, ViewChild} from '@angular/core';
import {MatPaginator, PageEvent} from '@angular/material/paginator';
import {MatSort} from '@angular/material/sort';
import {MatTableDataSource} from '@angular/material/table';
import { Title } from '@angular/platform-browser';
import { Router } from '@angular/router';
import { ClientService } from 'src/app/core/services/client.service';
import { MainService } from 'src/app/core/services/main.service';
import { Client } from 'src/app/models/client.model';

@Component({
  selector: 'app-list',
  templateUrl: './list.component.html',
  styleUrls: ['./list.component.css']
})
export class ListComponent implements AfterViewInit {

  clients: Client[];

  displayedColumns: string[] = ['client_name', 'client_address', 'client_home_phone', 'client_mobile_phone', 'client_status', 'buttons'];
  dataSource: MatTableDataSource<Client>;

  length = 0;

  @ViewChild(MatPaginator) paginator: MatPaginator;
  @ViewChild(MatSort) sort: MatSort;

  constructor(private changeDetectorRefs: ChangeDetectorRef, private router: Router, private titleService: Title, private mainService: MainService, private clientService: ClientService) {
    this.titleService.setTitle('Clients');
    this.mainService.setPageTitle('Clients');
    this.mainService.setButtonToolbar([
      {
        'url': 'create',
        'icon': 'add',
        'color': 'primary'
      },
    ]);

    this.clientService.list(25, 0).subscribe(clients => {
      this.clients = clients.data;
      this.dataSource = new MatTableDataSource(this.clients);
      this.length = clients.count;
      this.dataSource.paginator = this.paginator;
      this.dataSource.sort = this.sort;
    });
  }

  ngAfterViewInit() {

  }

  onChangedPage(pageData: PageEvent) {
    this.clientService.list(pageData.pageSize, pageData.pageIndex * pageData.pageSize).subscribe(clients => {
      this.clients = clients.data;
      this.dataSource = new MatTableDataSource(this.clients);
      this.length = clients.count;
      this.dataSource.sort = this.sort;
    });
  }

  applyFilter(event: Event) {
    const filterValue = (event.target as HTMLInputElement).value;
    this.clientService.list(this.paginator.pageSize, 0, filterValue).subscribe(clients => {
      this.clients = clients.data;
      this.dataSource = new MatTableDataSource(this.clients);
      this.length = clients.count;
      this.dataSource.sort = this.sort;
    });
  }

  onUpdate(id: String) {
    this.router.navigate(['/client/update/'+id]);
  }

  onDelete(id: string) {
    this.clientService.delete(id).subscribe(response => {
      if (response == 200) {
        this.clientService.list(this.paginator.pageSize, 0).subscribe(clients => {
          this.clients = clients.data;
          this.dataSource = new MatTableDataSource(this.clients);
          this.length = clients.count;
          this.dataSource.sort = this.sort;

          this.changeDetectorRefs.detectChanges();
        });
      }
    });
  }

}

client.service.ts

import { HttpClient, HttpHeaders } from "@angular/common/http";
import { Injectable } from "@angular/core";
import { map } from "rxjs/operators";
import { Client } from "src/app/models/client.model";
import { MainService } from 'src/app/core/services/main.service';

@Injectable()
export class ClientService {

  constructor(private http: HttpClient, private mainService: MainService) {}

  list(limit: number, offset: number, filter?: string) {
    let queryParams = '?limit='+limit+'&offset='+offset;
    if (filter) {
      queryParams += '&filter='+filter;
    }
    return this.http
    .get(this.mainService.getbaseApiUrl()+"client/list" + queryParams)
    .pipe(map(responseData => {
      const clientArray = [...responseData['rows']];

      return {data: clientArray, count: responseData['count']};
    }));
  }

  get(id: string) {
    return this.http
      .get(this.mainService.getbaseApiUrl()+"client/one/"+id);
  }

  add(client: Client) {
    return this.http
      .post(this.mainService.getbaseApiUrl()+'client/add', client, {
        headers: new HttpHeaders({
          // 'Origin': '*',
          //'Access-Control-Allow-Origin': '*',
          //'Access-Control-Allow-Credentials': 'true',
          'Content-Type':  'application/json',
        })
      });
  }

  update(client: Client) {
    return this.http
      .post(this.mainService.getbaseApiUrl()+'client/edit', client, {
        headers: new HttpHeaders({
          // 'Access-Control-Allow-Origin': '*',
          // 'Access-Control-Allow-Credentials': 'true',
          'Content-Type':  'application/json',
        })
      });
  }

  delete(id: string) {
    return this.http.delete(this.mainService.getbaseApiUrl()+'client/delete/'+id);
  }
}

I'm new to Angular and this may look simple, but I couldn't think of any solution. Is there any way for Angular to wait until the deletion is completed then refresh? The temporary solution is to use setTimeout so the mat table will refresh after waiting for X seconds, but I don't think that's a clean solution.

Please help.

UPDATE:

My temporary solution is to reload the current router.

app-routing.module.ts

@NgModule({
  imports: [RouterModule.forRoot(routes, {onSameUrlNavigation: 'reload'})],
  exports: [RouterModule]
})

list.component.ts

ngOnInit() {
  this.router.routeReuseStrategy.shouldReuseRoute = () => {
    return false;
  }
}

onDelete(id: string) {
    this.clientService.delete(id).subscribe(response => {
      if (response == 200) {
        this.router.navigate(['/client']);
      }
    });
}

But it will be great if there are other better solutions than this one.

1

There are 1 best solutions below

0
godocmat On
      onDelete(id: string) {
this.clientService.delete(id)
.pipe(switchMap(() => this.clientService.list(this.paginator.pageSize, 0)
.subscribe(clients => {
      this.clients = clients.data;
      this.dataSource = new MatTableDataSource(this.clients);
      this.length = clients.count;
      this.dataSource.sort = this.sort;

      this.changeDetectorRefs.detectChanges();
    });