webentwicklung-frage-antwort-db.com.de

Angular - Material Table, ist es möglich, Zeilen ohne vollständige Aktualisierung der Tabelle zu aktualisieren?

Nach ein paar Wochen Googeln und nur einer einzigen Stackoverflown-Frage konnte ich endlich meine Angular CRUD-App mit Material Table Component aufbauen. Es zeigt Daten vom Backend (JSON) und für CRUD-Operationen verwende ich Dialoge wie auf dem Bild gezeigt (dies ist ein Edit, tut mir leid für Kroatisch). Dialoge sind möglicherweise nicht der beste Weg, Inline-Bearbeitung ist möglicherweise besser. Für das Hinzufügen eines neuen Elements benötigen Sie jedoch einen Dialog.

 enter image description here

Das letzte, was mir noch wichtig ist, ist, wie man Felder in der Tabelle entsprechend aktualisiert. Wenn Sie also im Dialogfeld auf "Speichern" klicken, werden die Daten im Backend (in der MySQL-Tabelle) aktualisiert, jedoch nicht in der Frontansicht. Momentan habe ich eine hässliche Problemumgehung dafür. Jedes Mal, wenn Sie ein Update durchführen, wird auch die gesamte Tabelle aktualisiert.

Wie auch immer, hier ist der Code:

Tabellenkomponente:

export class BazaComponent implements OnInit {
  ....
  constructor(public httpClient: HttpClient, public dialog: MatDialog) {
  }

  ngOnInit() {
    this.loadData();
  }

  // TODO: Simplfy this...
  addNew(ident: number, naziv: string, mt: number, kutija: number,
         komada: number, jm: string, orginal: number, lokacija: number, napomena: string) {
    console.log('add new clicked');
    const dialogRef = this.dialog.open(AddDialogComponent, {
      data: {ident: ident, naziv: naziv, mt: mt, kutija: kutija,
        komada: komada, jm: jm, orginal: orginal, lokacija: lokacija, napomena: napomena }
    });

    dialogRef.afterClosed().subscribe(result => {
      console.log(result);
      if (result === 1) {
        this.loadData();  // --> This is a temp workaround, every time when I do CRUD operation just redraw whole thing again
      }
    });
  }

  startEdit(id: number, ident: number, naziv: string, mt: number, kutija: number,
            komada: number, jm: string, orginal: number, lokacija: number, napomena: string) {

    const dialogRef = this.dialog.open(EditDialogComponent, {
      data: {id: id, ident: ident, naziv: naziv, mt: mt, kutija: kutija,
        komada: komada, jm: jm, orginal: orginal, lokacija: lokacija, napomena: napomena}
    });

    dialogRef.afterClosed().subscribe(result => {
      if (result === 1) {
        this.loadData(); // --> This is a temp workaround, every time when I do CRUD operation just redraw whole thing again
      }
    });
  }

  deleteItem(id: number, ident: number, naziv: string, mt: number) {
    const dialogRef = this.dialog.open(DeleteDialogComponent, {
      data: {id: id, ident: ident, naziv: naziv, mt: mt}
    });

    dialogRef.afterClosed().subscribe(result => {
      if (result === 1) {
        this.loadData();
      }
    });
  }


  public loadData() {
    this.exampleDatabase = new DataService(this.httpClient);
    this.dataSource = new ExampleDataSource(this.exampleDatabase, this.paginator, this.sort);
    Observable.fromEvent(this.filter.nativeElement, 'keyup')
      .debounceTime(150)
      .distinctUntilChanged()
      .subscribe(() => {
        if (!this.dataSource) {
          return;
        }
        this.dataSource.filter = this.filter.nativeElement.value;
      });
  }
}


export class ExampleDataSource extends DataSource<Baza> {
  _filterChange = new BehaviorSubject('');

  get filter(): string {
    return this._filterChange.value;
  }

  set filter(filter: string) {
    this._filterChange.next(filter);
  }

  filteredData: Baza[] = [];
  renderedData: Baza[] = [];

  constructor(private _exampleDatabase: DataService,
              private _paginator: MatPaginator,
              private _sort: MatSort) {
    super();
    // Reset to the first page when the user changes the filter.
    this._filterChange.subscribe(() => this._paginator.pageIndex = 0);
  }

  /** Connect function called by the table to retrieve one stream containing the data to render. */
  connect(): Observable<Baza[]> {
    // Listen for any changes in the base data, sorting, filtering, or pagination
    const displayDataChanges = [
      this._exampleDatabase.dataChange,
      this._sort.sortChange,
      this._filterChange,
      this._paginator.page,
    ];

    this._exampleDatabase.getAllItems();

    return Observable.merge(...displayDataChanges).map(() => {
      // Filter data
      this.filteredData = this._exampleDatabase.data.slice().filter((item: Baza) => {
        const searchStr = (item.ident + item.naziv + item.mt + item.lokacija + item.napomena).toLowerCase();
        return searchStr.indexOf(this.filter.toLowerCase()) !== -1;
      });

      // Sort filtered data
      const sortedData = this.sortData(this.filteredData.slice());

      // Grab the page's slice of the filtered sorted data.
      const startIndex = this._paginator.pageIndex * this._paginator.pageSize;
      this.renderedData = sortedData.splice(startIndex, this._paginator.pageSize);
      return this.renderedData;
    });
  }

  disconnect() {
  }

  /** Returns a sorted copy of the database data. */
  sortData(data: Baza[]): Baza[] {
  ... sort stuff
}

Hier ist DataService, wo ich Feldaktualisierungen machen sollte:

import { Injectable } from '@angular/core';
import { HttpClient, HttpErrorResponse, HttpHeaders} from '@angular/common/http';
import { Baza } from '../models/kanban.baza';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';

    @Injectable()
    export class DataService {
      private readonly API_URL = 'http://localhost/api/'

      /** Stream that emits whenever the data has been modified. */
      dataChange: BehaviorSubject<Baza[]> = new BehaviorSubject<Baza[]>([]);

      constructor(private httpClient: HttpClient) {
      }

      get data(): Baza[] {
        return this.dataChange.value;
      }

      getAllItems(): void {
        this.httpClient.get<Baza[]>(this.API_URL).subscribe(data => {
          this.dataChange.next(data['items']);
        });
      }

    addItem(baza: Baza): void {
      this.httpClient.post(this.API_URL, Baza).subscribe(data => {
          //THIS WAS MY BEST TRY BUT IT DOESN'T WORK :(
          const copiedData = this.data.slice();
          copiedData.Push(baza);
          console.log(copiedData);
          this.dataChange.next(copiedData);
      });
    }


      updateItem(baza: Baza): void {
        this.httpClient.put(this.API_URL + baza.id, baza).subscribe();
      }

      deleteItem(id: number): void {
        this.httpClient.delete(this.API_URL + id, {headers: new HttpHeaders().set('Access-Control-Allow-Origin', '*')} ).subscribe();
    }
}

UPDATE 27.11.2017:

Okay, ich habe endlich herausgefunden, wie man eine neue Zeilenergänzung auslöst. Ich musste dataChange.value in der Tabellenkomponente aufrufen. Sobald Sie es mit einigen Daten laden, wird sofort eine neue Zeile angezeigt.

const data = {id: 208, ident: 233, naziv: 'test', mt: 291, komada: 2, jm: 'a', orginal: 100, lokacija: 3, napomena: 'pls work'};
this.exampleDatabase.dataChange.value.Push(data);

Dasselbe in DataService funktioniert nicht:

this.dataChange.value.Push(data); 

Plunker ist hier:

https://plnkr.co/edit/IWCVsBRl54F7ylGNIJJ3?p=info

EDIT 28.11.2017:

Jetzt bleibt nur noch die Logik zum Hinzufügen, Bearbeiten und Löschen. Für das Hinzufügen ist es einfach, es ist nur value.Push (Daten). Vielen Dank für die Hilfe.

10
besthiroeu

Ich habe einige Zeit gebraucht, aber ich habe endlich alles zum Laufen gebracht. Ihre Antworten und unterschiedlichen Ansätze haben auch geholfen. Hier ist meine CRUD-Implementierung, falls jemand Probleme damit hat:

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

Bildschirmfoto:Alt Text

Sie können auch die Projektdemo überprüfen: https://marinantonio.github.io/angular-mat-table-crud/

Die wichtigsten Teile befinden sich in der Datei table.ts:

....
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;
    }
}
....
15
besthiroeu

Wie Sie aus Ihrem Code erkennen, verwenden Sie die Paginierung. Nach der Grundoperation können Sie Folgendes tun: 

this.dataSource.paginator = this.paginator;

Dadurch wird die aktuelle Seite aktualisiert. Und ich bin froh, dass jemand aus Kroatien eckiges Material verwendet.

Hier ist der wichtige Teil meines Codes:

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;
}
6
zszep

Ein etwas anderer Ansatz zum Löschen eines Elements und zum Aktualisieren der Datentabelle. Es ruft die API erneut auf, dies funktioniert jedoch möglicherweise für kleinere Datensätze.

public deleteMember(memberId) {
      // Call the confirm dialog component
      this.confirmService.confirm('Confirm Delete', 'This action is final. Gone forever!')
          .switchMap(res => {if (res === true) {
              return this.appService.deleteItem(this.dbTable, memberId);
          }})
          .subscribe(
              result => {
                this.success();
                // Refresh DataTable to remove row.  This solution calls the db and is a hack.
                this.ngAfterViewInit();
              },
              (err: HttpErrorResponse) => {
                  console.log(err.error);
                  console.log(err.message);
                this.messagesService.openDialog('Error', 'Delete did not happen.');
              }
          );
  }

Dies wird natürlich oben in der Komponente aufgerufen, ist jedoch hier als Referenz enthalten.

private dbTable = 'members';
dataSource = new MatTableDataSource();

ngAfterViewInit() {
    this.appService = new AppService(this.http);
    this.dataSource.sort = this.sort;
    this.dataSource.paginator = this.paginator;


    // Populate the Material2 DataTable.
    Observable.merge(this.paginator.page)
      .startWith(null)  // Delete this and no data is downloaded.
      .switchMap(() => {
        return this.appService.getItems( this.dbTable,
          this.paginator.pageIndex);
      })
      .map(data => {
        return data.resource;
      })
      .subscribe(data => {
        this.dataLength = data.length;
        this.dataSource.data = data;
      });
  }
3
Preston

Diese Lösung verwendet meinen vorhandenen Löschcode, aber den gleichen für Aktualisierungscode. Das Hauptproblem ist das Finden des Array-Index für das bearbeitete oder gelöschte Element. Sobald das Ergebnis ein Erfolg ist, rufe ich ein Erfolgsmodal auf, um den Benutzer zu benachrichtigen, und dann eine Funktion, um die Zeile aus der Datentabelle zu entfernen. Oder Sie können die Daten in dieser Zeile mit etwas anderem Code aktualisieren, z. B. indem Sie die Daten in das Array von Objekten verschieben. Auf diese Weise müssen wir nicht alle Daten erneut herunterladen.

public deleteMember(memberId) {
      // Call the confirm dialog component
      this.confirmService.confirm('Confirm Delete', 'This action is final. Gone forever!')
          .switchMap(res => {if (res === true) {
              return this.appService.deleteItem(this.dbTable, memberId);
          }})
          .subscribe(
              result => {
                this.success();
                // Refresh DataTable to remove row.
                this.updateDataTable (memberId);
              },
              (err: HttpErrorResponse) => {
                  console.log(err.error);
                  console.log(err.message);
                this.messagesService.openDialog('Error', 'Delete did not happen.');
              }
          );
  }

Jetzt können Sie die gelöschte oder bearbeitete Zeile entfernen oder aktualisieren.

private dsData: any;
  // Remove the deleted row from the data table. Need to remove from the downloaded data first.
  private updateDataTable (itemId) {
    this.dsData = this.dataSource.data;
    if (this.dsData.length > 0) {
      for (let i = 0; i < this.dsData.length; i++ ) {
        if (this.dsData[i].member_id === itemId) {
          this.dataSource.data.splice(i, 1);
        }
      }
    }
    this.dataSource.paginator = this.paginator;
  }
3
Preston

Ich habe eine Problemumgehung beim Bearbeiten von Daten in der Tabelle, ohne modale Fenster zu verwenden. 

Sie können meine CRUD -Implementierung mit Angular 6 und Material betrachten. 

Datendienst

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);
 }
}

Komponente 

@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;
}

//snackBar
openSnackBar(message: string, action: string) {
    this.snackBar.open(message, action, {
        duration: 3000,
    });
}

//material dialog
openDialog(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/Angular6MaterialCRUD

Hier ist der Link zur Demo: https://crud-angular6.azurewebsites.net

Click here to see screenshot

3

Meine Antwort ist in Angular 6 Material 2 .

Ich habe die Funktion splice verwendet, die den Index der bearbeiteten Zeile als Argument verwendet, dann die Anzahl der zu löschenden Zeilen (in Ihrem Fall 1) und drittens die neue Version der bearbeiteten Zeile, die an diesem Index eingefügt wird:

dialogRef.afterClosed().subscribe(result => {
  if(result !== '' && result !== null) {
    const idx_editedRow = this.mattabledatasource.data.indexOf(row);
    this.mattabledatasource.data.splice(idx_editedRow, 1, result);
    loadData();
  }
});
2
arsanyf

Kannst du einen Blick darauf werfen? 

addItem(baza: Baza): void {
  this.httpClient.post(this.API_URL, Baza).subscribe(data => {
      //THIS WAS MY BEST TRY BUT IT DOESN'T WORK :(
      const copiedData = this.data.slice();
      copiedData.Push(baza);
      console.log(copiedData);
      this.dataChange.next(copiedData);
  });
}

Funktioniert die Anforderung POST und sendet die Daten? Sie verweisen auf Baza in der Anforderung POST, die 'baza' (Kleinbuchstabe B) sein sollte. Möglicherweise schlägt die Anforderung aus diesem Grund fehl und das beobachtbare Abonnement wird nie erfüllt. Sie können diese Theorie mit einem Fehlerbehandlungsprogramm für das Abonnement überprüfen.

addItem(baza: Baza): void {
  this.httpClient.post(this.API_URL, baza).subscribe(data => {
      const copiedData = this.data.slice();
      copiedData.Push(baza);
      console.log(copiedData);
      this.dataChange.next(copiedData);
  }, (errror) => {
    console.log(error);
  });
}

Schließlich würde sich mein Ansatz bei den Bearbeitungen leicht unterscheiden. Fügen Sie dieselbe Instanz des DataService in die Komponente ein, und übergeben Sie dieselbe Referenz an die Tabelle DataSource anstatt an eine neue Instanz. Übergeben Sie als Nächstes das gesamte Baza-Objekt, nicht nur seine Eigenschaften, an den Bearbeitungsdialog. Übergeben Sie als nächstes beim Schließen das ursprüngliche (unbearbeitete Objekt) sowie die neuen Eigenschaften (oder besser noch ein neues Objekt der Baza-Klasse mit den bearbeiteten Feldern). Senden Sie diese mit einer "Bearbeiten/Aktualisieren" -Methode an unseren Datendienst. Die Editier-/Aktualisierungsmethode filtert den vorhandenen Satz von Datenarrays nach Einträgen, die mit unserem unbearbeiteten Objekt übereinstimmen, und setzt sie auf das neue Objekt. Leicht abstrahiertes Beispiel unten

// z.B. Komponente

export class BazaComponent implements OnInit {
  ....
  constructor(
    public httpClient: HttpClient, 
    public dialog: MatDialog,
    public dataService: DataService
  ){}
  ....
  public loadData() {
    this.dataSource = new ExampleDataSource(this.dataService, this.paginator, this.sort);
    Observable.fromEvent(this.filter.nativeElement, 'keyup')
      .debounceTime(150)
      .distinctUntilChanged()
      .subscribe(() => {
        if (!this.dataSource) {
          return;
        }
        this.dataSource.filter = this.filter.nativeElement.value;
      });
  }
  ....
  startEdit(baza: Baza) {
    const dialogRef = this.dialog.open(EditDialogComponent, {
      data: {
        baza: baza
      }
    });

    dialogRef.afterClosed().subscribe(result => {
      // result will be simple array of our 'old' baza object that we passed in, and the 'new' baza object that contains the edits
      this.dataService.updateItem(result[0], result[1]);
    });
  }

  dialogRef.close(['close',editBaza,baza]);

// z.B. Bedienung

export class DataService {
  ....
  set data(data: Baza[]) {
    this.dataChange.next(data);
  }
  ....
  updateItem(oldBaza: Baza, newBaza: Baza){
    this.data = this.data.map((baza: Baza) => {
      if(baza === oldBaza) return newBaza;
      return baza;
    });
  }
2
NJ.

Struktur der Datei jobposting.component.ts:

export class JobPostingComponent implements OnInit {
  values: JobPosting[];
  columns: string[] = ['title', 'vacancies','division.name'];
  displayedColumns: string[] = ['actions'].concat(this.columns);
  dataSource: MatTableDataSource<JobPosting>;

Ich habe findIndex für die zu aktualisierende Zeile verwendet und die aktualisierten Werte der Zeile in den Index des Wertearrays eingefügt.

onEdit(data: JobPosting) {
  const dialogRef = this.dialog.open(AddJobPostingComponent, {
    data,
    width: '1000px'
  });

  dialogRef.afterClosed().subscribe(res => {
    if (res !== undefined) {
      const id = res.id;
      const index = this.values.findIndex(x => x.id === id);
      this.values[index] = res;
      this.dataSource.data = this.values;
    }
  });
}
1
Md. Rafee

Eigentlich haben Sie die Tabelle nach der Bearbeitung nicht aktualisiert, wenn Sie den folgenden HTML-Code haben:

<mat-table [dataSource]="dataSource" matSort>
      <ng-container matColumnDef="userName">
        <mat-header-cell mat-sort-header> UserName </mat-header-cell>
        <mat-cell *matCellDef="let row"> {{row.userName}} </mat-cell>
      </ng-container>
      <ng-container matColumnDef="actions">
        <mat-cell *matCellDef="let user">
          <button mat-icon-button matTooltip="Edit" (click)="editUser(user)">
            <mat-icon>edit</mat-icon>
          </button>
        </mat-cell>
      </ng-container>
      <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
      <mat-row *matRowDef="let row; columns: displayedColumns;">
      </mat-row>
</mat-table>

Und in den .ts haben Sie:

private editUser(user?: User) {
    let userTest: User = user;
    userTest.userName = "user123";
  }

Sie können die Zeile automatisch sehen, wenn Sie die Benutzernamenänderung ändern (in diesem Fall in "Benutzer123").

1
Juan Calderon