How to make an inline editable mat-table using the edit button in Angular?
To make inline editing in mat-table, not provide any documentation for that but ngPrime provide the edit table using the edit button.
So I m going to create a table with dynamic data and edit button in each row, when the user clicks on the edit button then instead of view edit mode will be open for that row only.
Html File
<mat-table
#table [dataSource]="dataSource"
matSort
[@animateStagger]="{value:'50'}"
>
<ng-container matColumnDef="sno">
<mat-header-cell *matHeaderCellDef>SNo.</mat-header-cell>
<mat-cell *matCellDef="let user;let i = index;">{{(paginator.pageIndex * paginator.pageSize)+i + 1}}</mat-cell>
</ng-container>
<ng-container matColumnDef="Name">
<mat-header-cell *matHeaderCellDef>Name</mat-header-cell>
<mat-cell *matCellDef="let user">
<ng-container *ngIf="!editUsr.Id || !user.Id || user.Id!==editUsr.Id">
<p class="text-truncate">{{user.Name || 'N/A'}} </p>
</ng-container>
<ng-container *ngIf="editUsr.Id && user.Id && user.Id===editUsr.Id">
<mat-form-field appearance="outline">
<input matInput placeholder="Name Name" [disabled]="editdisabled" name="name" [(ngModel)]="user.Name">
</mat-form-field>
</ng-container>
</mat-cell>
</ng-container>
<ng-container matColumnDef="isAct">
<mat-header-cell *matHeaderCellDef>Status</mat-header-cell>
<mat-cell *matCellDef="let user">
<ng-container *ngIf="!editUsr.Id || !user.Id || user.Id!==editUsr.Id">
<p class="text-truncate">{{user.IsActive?'Active':'Inactive'}}</p>
</ng-container>
<ng-container *ngIf="editUsr.Id && user.Id && user.Id===editUsr.Id">
<mat-form-field appearance="outline">
<mat-select placeholder="Select" [disabled]="editdisabled" name="isActive" [(ngModel)]="user.IsActive">
<mat-option [value]="true">Active</mat-option>
<mat-option [value]="false">Inactive</mat-option>
</mat-select>
</mat-form-field>
</ng-container>
</mat-cell>
</ng-container>
<!-- ACTION -->
<ng-container matColumnDef="action">
<mat-header-cell *matHeaderCellDef>Action</mat-header-cell>
<mat-cell *matCellDef="let user">
<span *ngIf="pagePerm && pagePerm.indexOf('u')!==-1">
<ng-container *ngIf="!editUsr.Id || !user.Id || user.Id!==editUsr.Id">
<mat-icon matTooltip="edit" (click)="editROw(user)">edit</mat-icon>
</ng-container>
<ng-container *ngIf="editUsr.Id && user.Id && user.Id===editUsr.Id">
<button mat-raised-button color="accent" matTooltip="Update" class="mr-10 mb-6" [disabled]="editdisabled" (click)="updateEdit()">Update</button>
<button mat-raised-button color="warn" matTooltip="Cancel" [disabled]="editdisabled" (click)="cancelEdit()">Cancel</button>
</ng-container>
</span>
<span *ngIf="!pagePerm || (pagePerm && pagePerm.indexOf('v')===-1 && pagePerm && pagePerm.indexOf('u')===-1)">N/A</span>
</mat-cell>
</ng-container>
<mat-header-row *matHeaderRowDef="displayedColumns; sticky:true"></mat-header-row>
<mat-row *matRowDef="let user; columns: displayedColumns;"></mat-row>
</mat-table>
When the user first time comes, then it looks like
TS File
Declare the variable that we need to
editUsr: any;oldUsr: any;editdisabled: boolean
After that declare functions for edit, update, cancel
editROw(usr: any){
console.log(usr)
this.editUsr = usr && usr.Id?usr:{};
this.oldUsr= {...this.editUsr};
}
updateEdit(){
//updateEdit
this.editdisabled = true;
this.userServ.updateUser(this.editUsr)
.subscribe((data: any) => {
this.editUsr= {};
this.editdisabled = false;
if(data.Data && data.Status==1){
this.oldUsr= {};
this.toastr.success(data.Message, 'Success!');
}else{
this.cancelEdit();
this.toastr.error(data.Message, 'Error!');
}
}, err => {
this.toastr.error("Please try after some time", 'Error!');
this.editdisabled = false;
this.cancelEdit();
});
}cancelEdit(){
//cancel
this.editUsr= {};
if(this.oldUsr&& this.oldUsr.Id){
this.dataListSubs = this.dataSource.usersData.pipe(
distinctUntilChanged()
).subscribe((data)=>{
if(data.length<=0){
}else{
let index = data.findIndex(item => item.Id === this.oldUsr.Id)
data.splice(index, 1, this.oldUsr)
this.dataSource.changeDataSource(data);
}
})
this.dataListSubs.unsubscribe();
console.log(this.oldUsr, 'this.oldUsr', this.dataSource.usersData)
}
}
In the above functions, when user click on the edit button then I m assigning that user to editUsr as well as oldUsr, using oldUser variable (if there is some problem saving or user cancel the button after changing data then we need to revert back to the same state as comes from the API)
Also for reflecting cancel changes, we need to add the method so that I can change data, distinctUntilChanged() is very much important as I am editing usersData dataSource inside subscribe so it calls every time but using the distinctUntilChanged() function it prevents that and calls only when data is changed from the previous one.
When user clicks on the edit button, edit looks like
DataSource file
export class UsersListDataSource implements DataSource<Users> {public usersData = new BehaviorSubject<Users[]>([]);private loadingUsers = new BehaviorSubject<boolean>(false);private countInfo = new BehaviorSubject<number>(0);public loading$ = this.loadingUsers.asObservable();public totalCount$ = this.countInfo.asObservable();constructor(private userServ: userService) {
}loadUsers(params: any) {
this.loadingUsers.next(true);
this.userServ.usersListing(params).pipe(
catchError((err) => of([err])),
finalize(() => this.loadingUsers.next(false))
)
.subscribe((data: any) => {
if (data['Data']) {
this.usersData.next(data['Data']);
this.countInfo.next(data[100]);
}else{
this.usersData.next([]);
this.countInfo.next(0);
}
});}connect(collectionViewer: CollectionViewer): Observable<Users[]> {
return this.usersData.asObservable();
}disconnect(collectionViewer: CollectionViewer): void {
this.usersData.complete();
this.loadingUsers.complete();
this.countInfo.complete();
}changeDataSource(data: Users[]){
this.usersData.next(data)
}}
changeDatSource function used when a user cancels the edit then I need to revert back to an old state, and for this, that function will be used.
loadUsers -> Call the API
connect -> using the observable method to connect the datasource
disconnect -> after everything disconnects all the subject behaviors
Happy Angular Material Table Coding
#materialTable #mattable #angularLove