'Angular 13 - material table new row, delete row update table

I am using Angular 13 material-table. I am able to successfully send a request to an api server.

I'm sending a successful post request using modal-dialog and registering. But I can't see it on the current table after registering, I see it in the table after refreshing the page.

Likewise, when I delete a record, it is not deleted from the table, I can see it in the table after the page is refreshed.

How can I fix this?

Here is the "material request lists" where my main table is located, in this area my table is available

material-demands-list

export class MaterialDemandsListComponent implements OnInit {
displayedColumns: string[] = [
    'id',
    'description',
    'createdUserId',
    'createdUserName',
    'status',
    'companyId',
    'companyName',
    'actions',
];

materials: MaterialDemandsModel[] = [];
dataSource = new MatTableDataSource<MaterialDemandsModel>(this.materials);
@ViewChild(MatPaginator, { static: false }) paginator!: MatPaginator;
@ViewChild(MatSort, { static: true }) sort!: MatSort;
@ViewChild(MatTable, { static: true }) table: MatTable<any> | any;

page: number = 1;
pageSize: number = 10;
totalCount: number = 0;
pageSizeOptions: number[] = [5, 10, 20, 50, 100];

workflows: WorkflowListModel[] = [];

constructor(
    private messageService: MessageService,
    public demandsService: MaterialDemandService,
    public workflowService: WorkflowListService,
    public dialog: MatDialog
) {}

ngOnInit(): void {
    this.getData(this.page, this.pageSize);
    this.dataSource.paginator = this.paginator;

    this.workflowService.getWorkflowDefinitions().subscribe((data) => {
    this.workflows = data.items;
    });
}

getData(page: Number, pageSize: Number) {
    this.demandsService
    .getMaterialDemands(Number(page), Number(pageSize))
    .subscribe((data) => {
        this.dataSource.data = data.data;
        this.totalCount = Number(data.data[0].totalCount);
        this.demandsService.loading = false;
    });
}

deleteDialog(obj: any): void {
    Confirm.show(
    `Delete row : ${obj.id}`,
    `${obj.description}  selected row deleting ?`,
    'Delete',
    'Cancel',
    () => {
        this.demandsService.deleteMaterialDemand(obj.id).subscribe({
        next: (v) => {},
        error: (e) => {
            console.log(e);
        },
        complete: () => {},
        });
    },
    () => {
        alert('Cancel');
    }
    );
}


onChangePage(pageEvent: PageEvent) {
    this.pageSize = pageEvent.pageSize;
    this.page = +pageEvent.pageIndex + 1;
    this.getData(this.page, this.pageSize);

    this.demandsService.loading = true;
}

openDialog(action: any, obj: any) {
    obj.action = action;
    const dialogRef = this.dialog.open(MaterialDemandDialogComponent, {
    data: obj,
    autoFocus: false,
    });
    dialogRef.disableClose = true;

    // send message to subscribers via observable subject
    this.messageService.sendMessage(this.workflows);

    dialogRef.afterClosed().subscribe((result) => {
    console.log(result);
    if (result.event == 'Add') {
        this.addRowData(result.data);
    } else if (result.event == 'Update') {
        this.updateRowData(result.data);
    }
    });
}
addRowData(row_obj: any) {
    console.log(row_obj);

    this.materials.push({
    id: 'row_obj.id',
    description: 'row_obj.description',
    ldapId: 'row_obj.ldapId',
    sAMAAccountName: 'row_obj.sAMAAccountName',
    objectGuid: 'row_obj.objectGuid',
    email: 'row_obj.email',
    preferredUserName: 'row_obj.preferredUserName',
    manager: 'row_obj.manager',
    companyName: 'row_obj.companyName',
    status: 'row_obj.status',
    companyId: "row_obj.companyId",
    workflowId: 'row_obj.workflowId',
    workflowDefinitionId: 'row_obj.workflowDefinitionId',
    workflowName: 'row_obj.workflowName',
    workflowVersion: "row_obj.workflowVersion",
    totalCount: "row_obj.totalCount",
    });
    this.table.renderRows();
}
updateRowData(row_obj: any) {
    this.materials = this.materials.filter((value, key) => {
    if (value.id == row_obj.id) {
        value.description = row_obj.description;
    }
    return true;
    });
}
}

In this modal form screen, I am creating a new record or updating an existing record.

material-demand-add-update-dialog

export class MaterialDemandDialogComponent implements OnInit, OnDestroy {
action: string | any;
local_data: any;

workflows: WorkflowListModel[] = []; //Workflow list

workflowsCtrl = new FormControl(); //autoComplete states
filteredStates: Observable<string[]> | any;
subscription: Subscription | any;

errorMessage = '';

@Input() material = {
    description: '',
    ldapId: '',
    sAMAAccountName: '',
    objectGuid: '',
    email: '',
    preferredUserName: '',
    manager: '',
    companyName: '',
    status: 'Boşta',

    workflowId: '',
    workflowDefinitionId: '',
    workflowName: '',
    workflowVersion: '',
    companyId: '1',
};
ownerForm: FormGroup | any;

constructor(
    private fb: FormBuilder,
    private messageService: MessageService,
    private materialDemandService: MaterialDemandService,
    public dialogRef: MatDialogRef<MaterialDemandDialogComponent>,
    @Optional() @Inject(MAT_DIALOG_DATA) public data: MaterialDemandsModel
) {
    this.local_data = { ...data };
    this.action = this.local_data.action;

    // subscribe to material-demands-list component -> workflow list messages
    this.subscription = this.messageService
    .getMessage()
    .subscribe((message) => {
        this.workflows = message.message;
        if (message) {
        //this.workflows.push(message.message);
        } else {
        this.workflows = [];
        }
    });
}

ngOnInit(): void {
    this.filteredStates = this.workflowsCtrl.valueChanges.pipe(
    startWith(''),
    map((state) =>
        state ? this._filterStates(state) : this.workflows.slice()
    )
    );

    //Validators
    this.ownerForm = this.fb.group({
    description: [
        this.local_data.description,
        [Validators.maxLength(250), Validators.required],
    ],
    workflowName: [
        this.local_data.workflowName,
        [Validators.maxLength(150), Validators.required],
    ],
    });
}


setWorkflowInfo(value: any) {
    this.material.workflowName = value.name;
    this.material.workflowDefinitionId = value.definitionId;
    this.material.workflowId = value.id;
    this.material.workflowVersion = value.version;
}



postMaterialDemand(): void {
    this.materialDemandService
    .postMaterialWithObservable(this.material)
    .subscribe({
        next: (v) => {
        console.log(v);
        },
        error: (e) => {
        this.errorMessage = e;
        console.log(e);
        },
        complete: () => {
        console.log('success');
        },
    });
}

doAction() {
    if (this.action === 'Add') {
    this.postMaterialDemand();
    }
    this.dialogRef.close({ event: this.action, data: this.local_data });
}
closeDialog() {
    this.dialogRef.close({ event: 'Cancel' });
}
ngOnDestroy(): void {
    this.subscription.unsubscribe();
}
}

My service file is as follows. I make sites like "Get, Post, Delete" here and it returns successfully.

service

export class MaterialDemandService {
private gatewayUrl: string = `${environment.gatewayUrl}`;
public loading: boolean = true;

constructor(private httpClient: HttpClient) {}

httpHeaders = new HttpHeaders({
    'Content-Type': 'application/json',
});

//GATEWAY -> POST
postMaterialWithObservable(data: any): Observable<MaterialDemandsModel> {
    let api = `${this.gatewayUrl}/api/services/purchasing/MaterialDemands`;

    return this.httpClient
    .post<any>(api, JSON.stringify(data), {
        headers: this.httpHeaders,
    })
    .pipe(
        tap((x) => {
        this.loading = false;
        }),
        retry(2),
        map(this.extractData),
        catchError(this.handleError)
    );
}

//GATEWAY -> GET -> get material demands 1/10
getMaterialDemands(page: number, pageSize: number) {
    return this.httpClient
    .get<{ data: MaterialDemandsModel[] }>(
        `${this.gatewayUrl}/api/services/purchasing/MaterialDemands/${page}/${pageSize}`
    )
    .pipe(
        retry(2),
        tap((x) => {
        this.loading = false;
        }),
        catchError(this.handleError)
    );
}


deleteMaterialDemand(materialId: Number) {
    return this.httpClient
    .delete<any>(
        `${this.gatewayUrl}/api/services/purchasing/MaterialDemands/${materialId}`,
        { headers: this.httpHeaders }
    )
    .pipe(retry(2), catchError(this.handleError));
}



private extractData(res: any) {
    return res;
}
private handleError(error: any) {
    let errorMessage = '';
    if (error.errorMessage instanceof ErrorEvent) {
    errorMessage = error.error.errorMessage;
    } else {
    errorMessage = `\nCode: ${error.status}}\nResponse: ${error.message}`;
    }
    window.alert(errorMessage);
    return throwError(() => {
    return errorMessage;
    });
}
}

I've been working on it for a few days but I couldn't figure it out.



Solution 1:[1]

I belive you have to provide a new refference for dataSource

In case of adding a new row you have to do something like this

this.dataSource = [...this.dataSource, newRow];

In case of deleting

this.dataSource = this.dataSource.filter(...)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1