Angular - Material Table, is it possible to update rows without entire table refresh? Angular - Material Table, is it possible to update rows without entire table refresh? angular angular

Angular - Material Table, is it possible to update rows without entire table refresh?


Took me some time but I finally got everything working. Your answers and different approaches helped aswell. So, here's my CRUD implementation if anyone gets in trouble with this:

https://github.com/marinantonio/angular-mat-table-crud

Screenshot:Alt Text

Or you can check project demo:https://marinantonio.github.io/angular-mat-table-crud/

Key parts are in table.ts file:

....addNew(issue: Issue) {    const dialogRef = this.dialog.open(AddDialogComponent, {      data: {issue: issue }    });    dialogRef.afterClosed().subscribe(result => {      if (result === 1) {        this.exampleDatabase.dataChange.value.push(this.dataService.getDialogData());        this.refreshTable();      }    });  }  startEdit(i: number, id: number, title: string, state: string, url: string, created_at: string, updated_at: string) {    this.index = i;    this.id2 = id;    console.log(this.index);    const dialogRef = this.dialog.open(EditDialogComponent, {      data: {id: id, title: title, state: state, url: url, created_at: created_at, updated_at: updated_at}    });    dialogRef.afterClosed().subscribe(result => {      if (result === 1) {        // Part where we do frontend update, first you need to find record using id        const foundIndex = this.exampleDatabase.dataChange.value.findIndex(x => x.id === this.id2);        // Then you update that record using dialogData        this.exampleDatabase.dataChange.value[foundIndex] = this.dataService.getDialogData();        // And lastly refresh table        this.refreshTable();      }    });  }  deleteItem(i: number, id: number, title: string, state: string, url: string) {    this.index = i;    this.id2 = id;    const dialogRef = this.dialog.open(DeleteDialogComponent, {      data: {id: id, title: title, state: state, url: url}    });    dialogRef.afterClosed().subscribe(result => {      if (result === 1) {        const foundIndex = this.exampleDatabase.dataChange.value.findIndex(x => x.id === this.id2);        this.exampleDatabase.dataChange.value.splice(foundIndex, 1);        this.refreshTable();      }    });  }  private refreshTable() {    // If there's no data in filter we do update using pagination, next page or previous page    if (this.dataSource._filterChange.getValue() === '') {      if (this.dataSource._paginator.pageIndex === 0) {        this.dataSource._paginator.nextPage();        this.dataSource._paginator.previousPage();      } else {        this.dataSource._paginator.previousPage();        this.dataSource._paginator.nextPage();      }      // If there's something in filter, we reset it to 0 and then put back old value    } else {      this.dataSource.filter = '';      this.dataSource.filter = this.filter.nativeElement.value;    }}....


As I see from your code that you are using pagination, you can do the following after the crud operation:

this.dataSource.paginator = this.paginator;

This will refresh the current page. And, glad someone from Croatia is using angular material.

Here's the important part from my code:

dialogRef.afterClosed().subscribe(result => {    if (result === null) { return; }    switch (mode) {               // add new        case 'C': {            data.push(result.vendor);            this.refreshTable();            break;        }        case 'U': {               // update            const index = data.findIndex((item) => item.buFmisVendorId === result.vendor.buFmisVendorId);            if (index > -1) {                data[index] = vendor;                this.refreshTable();            }            break;        }    }});private refreshTable() {    this.dataSource.paginator = this.paginator;}


I have some workaround in editing data in the table without using modal windows.

You can take a look at my CRUD implementation with Angular 6 and Material

Data service

import {Injectable} from '@angular/core';import {HttpClient, HttpParams, HttpHeaders} from '@angular/common/http';import {User} from './user';@Injectable()export class UserService{private url = "http://localhost:51120";constructor(private http: HttpClient){ }getUsers(){    let getUrl = this.url + "/api/all/";    return this.http.get(getUrl);}createUser(user: User){    let saveUrl = this.url + "/api/Users";    return this.http.post(saveUrl, user); }updateUser(id: number, user: User) {    const urlParams = new HttpParams().set("id", id.toString());    return this.http.post(this.url + "/api/update", user);}deleteUser(id: number){    const urlParams = new HttpParams().set("id", id.toString());    return this.http.delete(this.url + "/api/delete/" + id); }}

Component

@Component({selector: 'app-root',templateUrl: './app.component.html',styleUrls: ['./app.component.css'],providers: [UserService]})export class AppComponent implements OnInit {@ViewChild(MatPaginator) paginator: MatPaginator;addNewUser: User[] = [    { Id: 0, Name: null, Age: null, Email: null, Surname: null }];users: Array<User>;showTable: boolean;statusMessage: string;isLoaded: boolean = true;displayedColumnsUsers: string[] = ['Id', 'Name', 'Surname', 'Age', 'Email', 'Change', 'Delete'];displayedColumnsAddUser: string[] = ['Name', 'Surname', 'Age', 'Email', 'Save', 'Cancel'];dataSourceUsers: any;dataSourceAddUser: any;newUser : User;constructor(private serv: UserService, public dialog: MatDialog, public snackBar: MatSnackBar) {    this.users = new Array<User>();}@ViewChild(MatSort) sort: MatSort;ngOnInit() {    this.loadUsers();    this.dataSourceAddUser = new MatTableDataSource();}applyFilter(filterValue: string) {    this.dataSourceUsers.filter = filterValue.trim().toLowerCase();    if (this.dataSourceUsers.paginator) {        this.dataSourceUsers.paginator.firstPage();    }}private loadUsers() {    this.isLoaded = true;    this.serv.getUsers().subscribe((data: User[]) => {        this.users = data;        this.users.sort(function (obj1, obj2) {            // Descending: first id less than the previous            return obj2.Id - obj1.Id;        });        this.isLoaded = false;        this.dataSourceUsers = new MatTableDataSource(this.users);        this.dataSourceAddUser = new MatTableDataSource(this.addNewUser);        this.dataSourceUsers.sort = this.sort;        this.dataSourceUsers.paginator = this.paginator;    },        error => {            alert("Error: " + error.name);            this.isLoaded = false;        }    );}deleteUserForDialog(user: User) {    this.serv.deleteUser(user.Id).subscribe(data => {        this.statusMessage = 'User ' + user.Name + ' is deleted',            this.openSnackBar(this.statusMessage, "Success");        this.loadUsers();    })}editUser(user: User) {    this.serv.updateUser(user.Id, user).subscribe(data => {        this.statusMessage = 'User ' + user.Name + ' is updated',        this.openSnackBar(this.statusMessage, "Success");        this.loadUsers();    },        error => {            this.openSnackBar(error.statusText, "Error");        }    );}saveUser(user: User) {    if (user.Age != null && user.Name != null && user.Name != "" && user.Age != 0) {        this.serv.createUser(user).subscribe(data => {            this.statusMessage = 'User ' + user.Name + ' is added',            this.showTable = false;            this.openSnackBar(this.statusMessage, "Success");            this.loadUsers();        },            error => {                this.showTable = false;                this.openSnackBar(error.statusText, "Error");            }        );    }    else {        this.openSnackBar("Please enter correct data", "Error")    }}show() {    this.showTable = true;    this.addNewUser = [{ Id: 0, Name: null, Age: null, Email: null, Surname: null }];}cancel() {    this.showTable = false;}//snackBaropenSnackBar(message: string, action: string) {    this.snackBar.open(message, action, {        duration: 3000,    });}//material dialogopenDialog(element): void {    const dialogRef = this.dialog.open(DialogOverviewExampleDialogComponent, {        width: '250px',        data: element,    });    dialogRef.afterClosed().subscribe(result => {        console.log('The dialog was closed');        if (result == "Confirm") {            this.deleteUserForDialog(element);        }    });}//   Form field with error messages name = new FormControl('', [Validators.required]);getErrorMessage() {    return this.name.hasError('required') ? 'You must enter a value' :        this.name.hasError('name') ? 'Not a valid name' : '';}age = new FormControl('', [Validators.required]);email = new FormControl('', [Validators.required, Validators.email]);surnameFormControl= new FormControl('', [Validators.required]);emailGetErrorMessage() {    return this.email.hasError('required') ? 'You must enter a value' :        this.email.hasError('email') ? 'Not a valid email' :            '';}onSubmit(newUser:User){    this.newUser = new User(0,"",0,"","");}}

https://github.com/AleksandrChuikov/AngularMaterialCRUD

Here is the link to demo:https://crud-angular6.azurewebsites.net

Updated to Angular 8

Updated to Angular 12

Click here to see screenshot