简体   繁体   中英

Angular Material mat-table is not reloading data on datasource update

I'm trying to update a mat-table datasource for data reloading. In this case I have this component:

import {
  AfterViewInit,
  Component,
  Input,
  OnInit,
  ViewChild,
} from '@angular/core';
import { MatPaginator } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table';
import { first } from 'rxjs/operators';
import { EmployeeService } from '../_services/employee.service';

export interface Elem {
  test: string;
  test1: string;
  test2: string;
  test3: string;
  test4: string;
  test5: string;
}

@Component({
  selector: 'app-employee-table',
  templateUrl: './employee-table.component.html',
  styleUrls: ['./employee-table.component.css'],
})
export class EmployeeTableComponent implements OnInit {
  displayedColumns: string[] = [
    'fullName',
    'role',
    'manager',
    'counselor',
    'action',
  ];
  dataSource: any;
  loading = false;

  @Input() areDataUpdated!: boolean;

  @ViewChild(MatSort) sort: MatSort | undefined;
  @ViewChild(MatPaginator) paginator: MatPaginator | undefined;
  constructor(private employeeService: EmployeeService) {}

  ngOnInit(): void {
    this.onEmployeesLoading();
  }

  ngOnChanges(): void {
    if (this.areDataUpdated) {
      this.onEmployeesLoading();
    }
  }

  onEmployeesLoading() {
    this.loading = true;
    this.dataSource = null;

    this.employeeService
      .getAll()
      .pipe(first())
      .subscribe((employees) => {
        console.log(employees);
        this.dataSource = new MatTableDataSource(employees);
        this.dataSource.paginator = this.paginator;
        this.dataSource.sort = this.sort;
        this.loading = false;
        this.areDataUpdated = false;
      });
  }

  onEmployeeDelete(id: number) {
    this.loading = true;
    this.dataSource = null;

    this.employeeService
      .deleteById(id)
      .pipe(first())
      .subscribe((employee) => {
        console.log(employee);
        this.dataSource = new MatTableDataSource(employee);
        this.dataSource.paginator = this.paginator;
        this.dataSource.sort = this.sort;
        this.loading = false;
      });
  }
}

When I delete an item, I call the onEmployeeDelete, the dataSource is emptied, and through the employeeService I go for delete and reload new data. It works well. Instead, when I try to add a new employee, the areDataUpdated input is switched to true, and the ngOnChanges method is launched. areDataUpdated is true, so the onEmployeesLoading is called and data are retrieved through HTTP from backend. But in this case, table is not emptied and data are not updated.

So, in this method

onEmployeesLoading() {
    this.loading = true;
    this.dataSource = null;

    this.employeeService
      .getAll()
      .pipe(first())
      .subscribe((employees) => {
        console.log(employees);
        this.dataSource = new MatTableDataSource(employees);
        this.dataSource.paginator = this.paginator;
        this.dataSource.sort = this.sort;
        this.loading = false;
        this.areDataUpdated = false;
      });
  }

These rows are ignored

this.loading = true;
this.dataSource = null;

despite this are ignored, the console.log in the subscribe method shows up data, with new employee added correctly

I don't understand what's the difference with the onEmployeeDelete method, except of the fact that the onEmployeesLoading is called in a lifecycle hook

Try to set the datesource like this:

@Component({
  selector: 'app-employee-table',
  templateUrl: './employee-table.component.html',
  styleUrls: ['./employee-table.component.css'],
})
export class EmployeeTableComponent implements OnInit {
  displayedColumns: string[] = [
    'fullName',
    'role',
    'manager',
    'counselor',
    'action',
  ];
  dataSource = new MatTableDataSource(any);
  
  ...
  ...

When then getting the the employees from the get request you can set the datasource like this:

onEmployeesLoading() {
    this.loading = true;

    this.employeeService
      .getAll()
      .pipe(first())
      .subscribe((employees) => {
        console.log(employees);
        this.dataSource.data = emplyoees;
        this.dataSource.paginator = this.paginator;
        this.dataSource.sort = this.sort;
        this.loading = false;
        this.areDataUpdated = false;
      });
  }

This way you do not have to set a new datasource every time you make a get request.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM