Hi, in any application we mostly
show the data in tabular format and user like that data handling, if we provide
them multiple options to view the data. like in our one of the previous posts
(click here to go to the post) we have seen how to add pagination, searching
and sorting etc to the angular material table so the user can use that according to
his need.
In this post, we are going to add
one more feature to our angular material table that is, hide/show columns
dynamically or we also can say add/remove columns dynamically. We are going to
do that in angular purely, we are not going to install any third-party plugin
or library. Let’s do it.
[If you have any problem related to the Angular material table please check our following posts:
Click here for a simple material table with searching, sorting, and pagination,
Click here for inline editing and validation with template-driven forms in the angular material table,
Click here for multiple expandable rows in the angular material table,
Click here for a table inside a row and multiple paginators in the angular material table
Click here for adding custom and common filter/search in the angular material table]
following is the HTML file of our angular component, in this we have
added angular material table and added some basic features like pagination
searching sorting. Just above the table, we have added a material menu to show the
list of columns that we are having in our table and we have provided the slide
toggle-button to hide/show the column.
<div class="body">
<div class="row">
<div class="text-center col-lg-12">
<h4 class="form-control">Angular - Dynamically hide-show or add-remove columns in angular material table
</h4>
</div><br><br>
</div>
<div class="row">
<div class="col-lg-2"></div>
<div class="col-lg-8 center">
<div class="spinner-container" *ngIf="userListMatTabDataSource.loading$ | async">
<mat-spinner></mat-spinner>
</div>
<div class="card">
<div class="thead">
<label for="Table">Demo Table</label>
<button style="float:right" class="btn btn-sm btn-primary top-margin" #menuTrigger="matMenuTrigger"
[matMenuTriggerFor]="mainMenuButton">
hide/show
</button>
<mat-menu #mainMenuButton="matMenu">
<span (click)="$event.stopPropagation()" *ngFor="let column of columnShowHideList;index as i">
<mat-slide-toggle [(ngModel)]="column.isActive" (change)="toggleColumn(column)">
</mat-slide-toggle>
{{column.name}}
<br>
</span>
</mat-menu>
<input type="text" style="float:right" (keyup)="applyFilter($event.target.value)"
placeholder="search for" class="form-control-sm top-margin">
</div>
<mat-table class="mat-elevation-z8" [dataSource]="userListMatTabDataSource" matSort
matSortActive="userName" matSortDirection="asc" matSortDisableClear>
<ng-container matColumnDef="srno">
<mat-header-cell *matHeaderCellDef>Sr No</mat-header-cell>
<mat-cell *matCellDef="let user; let i = index;">
{{i+1}}
</mat-cell>
</ng-container>
<ng-container matColumnDef="userName">
<mat-header-cell *matHeaderCellDef mat-sort-header>User Name</mat-header-cell>
<mat-cell *matCellDef="let user">
{{user.userName}}
</mat-cell>
</ng-container>
<ng-container matColumnDef="email">
<mat-header-cell *matHeaderCellDef mat-sort-header>Email</mat-header-cell>
<mat-cell *matCellDef="let user">
{{user.email}}
</mat-cell>
</ng-container>
<ng-container matColumnDef="contactNo">
<mat-header-cell *matHeaderCellDef mat-sort-header>Contact No</mat-header-cell>
<mat-cell *matCellDef="let user">
{{user.contactNo}}
</mat-cell>
</ng-container>
<ng-container matColumnDef="address">
<mat-header-cell *matHeaderCellDef mat-sort-header>Address</mat-header-cell>
<mat-cell *matCellDef="let user">
{{user.address}}
</mat-cell>
</ng-container>
<mat-header-row *matHeaderRowDef="columnList"></mat-header-row>
<mat-row *matRowDef="let row; columns: columnList; let i = index;"
[class.selected]="selectedRow == row.id" (click)="rowClick(row.id)">
</mat-row>
</mat-table>
<mat-paginator [pageSizeOptions]="[3, 5, 10]" showFirstLastButtons></mat-paginator>
</div>
</div>
</div>
</div>
After HTML let’s see the typescript file. Here we have done all
basic things to show data and add paginator, searching, sorting in the angular
material table and what additional we have done is, we have added one extra
array to hold hide/show status of the column. While storing status we also need to
store the position of the column so when we are going to add/show column again, we
can show it to the original position. After that, we have added all columns with
other needed data in that extra array, in initializeColumnProperties function.
Once everything is set we have added toggleColumn function to hide/show columns,
in that function, we have checked if toggle slide is false then simply remove the column from the material
table and if it is true then check for the position and push the column to the
particular position.
The following code will make
you understand everything.
import { Component, ViewChild, OnInit } from '@angular/core';
import { User } from './user/User';
import { MatTableDataSource, MatPaginator, MatSort } from '@angular/material';
interface CustomColumn {
possition: number;
name: string;
isActive: boolean;
}
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
userList: User[];
selectedRow: number;
editedRows: boolean[];
public columnList = ['srno', 'userName', 'email', 'contactNo', 'address'];
public columnShowHideList: CustomColumn[] = [];
userListMatTabDataSource = new MatTableDataSource<User>(this.userList);
@ViewChild(MatPaginator) paginator: MatPaginator;
@ViewChild(MatSort) sort: MatSort;
constructor() { }
ngOnInit() {
this.initializeColumnProperties();
this.editedRows = [];
this.getAlldata();
console.log(this.userList);
this.userListMatTabDataSource.paginator = this.paginator;
this.userListMatTabDataSource.sort = this.sort;
}
applyFilter(filterValue: string) {
this.userListMatTabDataSource.filter = filterValue.trim().toLowerCase();
}
toggleColumn(column) {
if (column.isActive) {
if (column.possition > this.columnList.length - 1) {
this.columnList.push(column.name);
} else {
this.columnList.splice(column.possition, 0, column.name);
}
} else {
let i = this.columnList.indexOf(column.name);
let opr = i > -1 ? this.columnList.splice(i, 1) : undefined;
}
}
initializeColumnProperties() {
this.columnList.forEach((element, index) => {
this.columnShowHideList.push(
{ possition: index, name: element, isActive: true }
);
});
// After for loop it will look like this
// public columnShowHideList = [
// { possition: 0, name: 'action', isActive: true },
// { possition: 1, name: 'userName', isActive: true },
// { possition: 2, name: 'email', isActive: true },
// { possition: 3, name: 'contactNo', isActive: true },
// { possition: 4, name: 'address', isActive: true }
// ];
}
getAlldata() {
this.userList = [
{
id: 1, userName: 'Ramesh', password: 'rebqwtye', email: 'ramesh@gmail.com',
contactNo: '9788235466', address: '123 RG Road, XYCity', edited: undefined
},
{
id: 2, userName: 'Suresh', password: 'rebqwtye', email: 'suresh@gmail.com',
contactNo: '9788235466', address: '123 RG Road, XYCity', edited: undefined
},
{
id: 3, userName: 'Ganesh', password: 'rebqwtye', email: 'ganesh@gmail.com',
contactNo: '9788235466', address: '123 RG Road, XYCity', edited: undefined
},
{
id: 4, userName: 'Bhavesh', password: 'rebqwtye', email: 'bhavesh@gmail.com',
contactNo: '9788235466', address: '123 RG Road, XYCity', edited: undefined
},
{
id: 5, userName: 'Bhavesh', password: 'rebqwtye', email: 'bhavesh@gmail.com',
contactNo: '9788235466', address: '123 RG Road, XYCity', edited: undefined
},
{
id: 6, userName: 'Bhavesh', password: 'rebqwtye', email: 'bhavesh@gmail.com',
contactNo: '9788235466', address: '123 RG Road, XYCity', edited: undefined
},
{
id: 7, userName: 'Bhavesh', password: 'rebqwtye', email: 'bhavesh@gmail.com',
contactNo: '9788235466', address: '123 RG Road, XYCity', edited: undefined
}
];
this.userListMatTabDataSource.data = this.userList;
}
rowClick(rowId) {
this.selectedRow = rowId;
}
}
export class User {
id: Number;
userName: String;
password: String;
email: String;
contactNo: String;
address: String;
edited: Boolean;
constructor() { };
}
Above is the model or
type to hold the user data and to assign it to the material table.
We have not imported anything out of the angular library, here is the module
file.
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { FormsModule } from '@angular/forms';
import {
MatTableModule,
MatPaginatorModule,
MatProgressSpinnerModule,
MatFormFieldModule,
MatInputModule,
MatSortModule,
MatButtonModule,
MatMenuModule,
MatSlideToggleModule
} from '@angular/material';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
AppRoutingModule,
FormsModule,
MatTableModule,
MatPaginatorModule,
MatProgressSpinnerModule,
MatInputModule,
MatButtonModule,
MatFormFieldModule,
BrowserAnimationsModule,
MatSortModule,
MatMenuModule,
MatSlideToggleModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
Output
And that’s it,
Hope you like it.
Here you can download the project Click here to download the project
When you download the project, at the very first run command “npm install”.
Because of the size issue, we are not going to upload the node module folder
onwards.
Link to download all your examples is broken?
ReplyDeleteit is working
DeleteCan you provide a demo so that it gets clear what it's exactly what users want
ReplyDeleteif you click on "Click here to download the project" you will get the project
DeleteI have built and ran this example, but it shows error in line userListMatTabDataSource = new MatTableDataSource(this.userList);
ReplyDeletesrc/app/reporting/demo/demo.component.ts:22:3
22 userList: User[];
~~~~~~~~
'userList' is declared here.
check if you have imported all properly.
Delete