In this Angular tutorial, we are going to learn how to implement a Material table in Angular 10/9/8/7/6/5 application and perform inline CRUD operations using a dialog modal.
We’ll be creating a datatable grid with the Angular Material Table component which will have some basic operations like Add, Update and Delete rows using the Dialog component.
Angular Material Table component is full of features and a wide variety of options are available to create data-rich grids in a very optimized way. It provides a lot basic to advance functionalities like filter, sorting, pagination, expand-collapse, custom templating, etc.
But discussion of these features is out of the scope of this article, so let’s stick to some basic operations we are going to implement like Add, Delete and Update table rows.
To do these operations on table rows, we’ll use the Dialog component on Angular material. A dialog is a popup layout that is displayed to a user above all content in the center of the screen, which can easily catch user eyeballs. Dialog component can be used in many areas like getting prompt responses, showing alert messages, notifying users, getting other user inputs, etc.
To keep this simple we will have two fields in table i.e ID and Name with an extra Action column to have Edit and Delete control links.
So, let’s get to work…
Create a new Angular Project
We will start with a new Angular project, using Angular CLI tool is very easy and quick to start with a project.
# Install Angular CLI
$ npm install -g @angular/cli
# Create new project
$ ng new angular-material-table-inline-ops
# Enter project
$ cd angular-material-table-inline-ops
# Run project in VS Code
$ code .
Install Material Package
Run the following command to install the Material package
$ ng add @angular/material
Answer a few questions asked to do configuration in the Angular project
# ? Choose a prebuilt theme name, or "custom" for a custom theme: Indigo/Pink
# ? Set up global Angular Material typography styles? Yes
# ? Set up browser animations for Angular Material? Yes
That’s it … we are done with Angular Material installation and configuration.
Update App Module
We are going to use Table, Dialog, FormFields, Input, Buttons as Material components in our tutorial. So we need to import these in the app.module.ts file and also add in the imports
array to use them in the application.
Also, import FormsModule
as we will use [(ngModel)]
in our Dialog.
// app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { FormsModule } from '@angular/forms';
import { MatTableModule } from '@angular/material/table';
import { MatDialogModule } from '@angular/material/dialog';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { MatButtonModule } from '@angular/material/button';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
BrowserAnimationsModule,
FormsModule,
MatTableModule,
MatDialogModule,
MatFormFieldModule,
MatInputModule,
MatButtonModule,
MatInputModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
Create Material Table
Now update the App Component template to implement a Material Datatable. The Material datatable is created by adding the <table>
with the mat-table
directive.
The [dataSource]
property takes a collection of data passed to the data table.
Each column is created by adding an ng-container
element with matColumnDef
identifier. The last column is for action links to Edit and Delete operations. We are calling the openDialog()
method and passing action needs to be performed. We’ll add the method definition later in the component class.
# Update HTML Template
Update the app.component.html as shown below:
<!-- app.component.html -->
<div class="container text-center">
<button mat-button (click)="openDialog('Add',{})" mat-flat-button color="primary">Add Row</button>
<table mat-table [dataSource]="dataSource" #mytable class="my-table mat-elevation-z8">
<!--- Note that these columns can be defined in any order.
The actual rendered columns are set as a property on the row definition" -->
<!-- Id Column -->
<ng-container matColumnDef="id">
<th mat-header-cell *matHeaderCellDef> ID. </th>
<td mat-cell *matCellDef="let element"> {{element.id}} </td>
</ng-container>
<!-- Name Column -->
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef> Name </th>
<td mat-cell *matCellDef="let element"> {{element.name}} </td>
</ng-container>
<!-- Action Column -->
<ng-container matColumnDef="action">
<th mat-header-cell *matHeaderCellDef> Action </th>
<td mat-cell *matCellDef="let element" class="action-link">
<a (click)="openDialog('Update',element)">Edit</a> |
<a (click)="openDialog('Delete',element)">Delete</a>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
</div>
The #mytable
is a template variable which we will use to refresh table data by calling renderRows()
method inside the class component.
<strong>*matHeaderRowDef</strong>
takes an array of columns we want to show in the table.<strong>matColumnDef</strong>
property on the column is the same as a key in the JSON data object.*matHeaderCellDef
have the text of columns in the table header.# Update App Component Class
//app.component.ts
import { Component, ViewChild } from '@angular/core';
import { MatTable } from '@angular/material/table';
import { MatDialog } from '@angular/material/dialog';
import { DialogBoxComponent } from './dialog-box/dialog-box.component';
export interface UsersData {
name: string;
id: number;
}
const ELEMENT_DATA: UsersData[] = [
{id: 1560608769632, name: 'Artificial Intelligence'},
{id: 1560608796014, name: 'Machine Learning'},
{id: 1560608787815, name: 'Robotic Process Automation'},
{id: 1560608805101, name: 'Blockchain'}
];
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
displayedColumns: string[] = ['id', 'name', 'action'];
dataSource = ELEMENT_DATA;
@ViewChild(MatTable,{static:true}) table: MatTable<any>;
constructor(public dialog: MatDialog) {}
openDialog(action,obj) {
obj.action = action;
const dialogRef = this.dialog.open(DialogBoxComponent, {
width: '250px',
data:obj
});
dialogRef.afterClosed().subscribe(result => {
if(result.event == 'Add'){
this.addRowData(result.data);
}else if(result.event == 'Update'){
this.updateRowData(result.data);
}else if(result.event == 'Delete'){
this.deleteRowData(result.data);
}
});
}
addRowData(row_obj){
var d = new Date();
this.dataSource.push({
id:d.getTime(),
name:row_obj.name
});
this.table.renderRows();
}
updateRowData(row_obj){
this.dataSource = this.dataSource.filter((value,key)=>{
if(value.id == row_obj.id){
value.name = row_obj.name;
}
return true;
});
}
deleteRowData(row_obj){
this.dataSource = this.dataSource.filter((value,key)=>{
return value.id != row_obj.id;
});
}
}
let’s back to app.component.ts explanation. Here we have Table data to populate and @ViewChild
to get table reference.
The openDialog()
method is getting action string for Add, Update and Delete and obj as row object to pass in open()
method
Also subscribed to Dialog close event using afterClosed()
method calling addRowData(), updateRowData()
and deleteRowData()
as per event sent back from DialogBoxComponent close()
method
openDialog(action,obj) {
obj.action = action;
const dialogRef = this.dialog.open(DialogBoxComponent, {
width: '250px',
data:obj
});
dialogRef.afterClosed().subscribe(result => {
if(result.event == 'Add'){
this.addRowData(result.data);
}else if(result.event == 'Update'){
this.updateRowData(result.data);
}else if(result.event == 'Delete'){
this.deleteRowData(result.data);
}
});
}
Create a Dialog Component
$ ng generate component dialog-box --skipTests=true
--skipTests=true
will create component without spec.ts test files
# Update the Dialog Component
Update the dialog-box.component.ts file with following code:
//dialog-box.component.ts
import { Component, Inject, Optional } from '@angular/core';
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
export interface UsersData {
name: string;
id: number;
}
@Component({
selector: 'app-dialog-box',
templateUrl: './dialog-box.component.html',
styleUrls: ['./dialog-box.component.scss']
})
export class DialogBoxComponent {
action:string;
local_data:any;
constructor(
public dialogRef: MatDialogRef<DialogBoxComponent>,
//@Optional() is used to prevent error if no data is passed
@Optional() @Inject(MAT_DIALOG_DATA) public data: UsersData) {
console.log(data);
this.local_data = {...data};
this.action = this.local_data.action;
}
doAction(){
this.dialogRef.close({event:this.action,data:this.local_data});
}
closeDialog(){
this.dialogRef.close({event:'Cancel'});
}
}
MAT_DIALOG_DATA
is used to get data passed in the open method’s data parameter from the App component. The MatDialogRef
class is used to perform actions on opened Dialog modal. This will be used to close Dialog after the action is successfully performed.<!-- dialog-box.component.html -->
<h1 mat-dialog-title>Row Action :: <strong>{{action}}</strong></h1>
<div mat-dialog-content>
<mat-form-field *ngIf="action != 'Delete'; else elseTemplate">
<input placeholder="{{action}} Name" matInput [(ngModel)]="local_data.name">
</mat-form-field>
<ng-template #elseTemplate>
Sure to delete <b>{{local_data.name}}</b>?
</ng-template>
</div>
<div mat-dialog-actions>
<button mat-button (click)="doAction()">{{action}}</button>
<button mat-button (click)="closeDialog()" mat-flat-button color="warn">Cancel</button>
</div>
Also, check how to add extra rows on the Angular Material table and implement Expand/ Collapse functionality by clicking inside each row and multiple rows by clicking on the master button. The master button will toggle expand/ collapse on multiple rows … Read more
That’s it now run the application using
$ ng serve --open
it will look something like this
If you see some errors like this when opening the Dialog:
Can’t bind to ‘ngIf’ since it isn’t a known property of ‘mat-form-field’.
logUnknownPropertyError
Can’t bind to ‘ngIfElse’ since it isn’t a known property of ‘mat-form-field’.
Then make sure you have added the DialogBoxComponent
under the declarations
array in the app.module.ts file.
Angular Material 13 Table Inline Datepicker Edit Mode Tutorial
Also, check
- Expand Collapse Material Datatable Rows on Master Button Click
- Inline Material Datatable Edit Rows
- Material Datatable | “No Rows Found” message and remove Pagination
- Material Table Column Width, Text Alignment Customization
Conclusion
So here we used Angular Material to build a Datatable with Edit, Delete and Add actions to operate on table rows using Dialog. We also get to know How to pass data from the parent component to the Dialog box and get back a response in the parent component.
You can buy iqos products iqos heets terea antalya 7/24 with whatsapp or call…
Leave a Reply