Angular Material is a popular UI framework based on Material Design for Angular.
In this article, we’ll look at how to use Angular Material into our Angular project.
Tables
We can add a table with Material Design style with Angular Material.
For example, we can write:
app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { MatTableModule } from '@angular/material/table';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
AppRoutingModule,
BrowserAnimationsModule,
MatTableModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
app.component.ts
import { Component } from '@angular/core';
export interface PeriodicElement {
name: string;
position: number;
weight: number;
symbol: string;
}
const ELEMENT_DATA: PeriodicElement[] = [
{ position: 1, name: 'Hydrogen', weight: 1.0079, symbol: 'H' },
{ position: 2, name: 'Helium', weight: 4.0026, symbol: 'He' },
{ position: 3, name: 'Lithium', weight: 6.941, symbol: 'Li' },
{ position: 4, name: 'Beryllium', weight: 9.0122, symbol: 'Be' },
{ position: 5, name: 'Boron', weight: 10.811, symbol: 'B' },
];
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
displayedColumns: string[] = ['position', 'name', 'weight', 'symbol'];
dataSource = ELEMENT_DATA;
}
app.component.html
<div>
<table mat-table [dataSource]="dataSource" class="mat-elevation-z8">
<ng-container matColumnDef="position">
<th mat-header-cell *matHeaderCellDef> No. </th>
<td mat-cell *matCellDef="let element"> {{element.position}} </td>
</ng-container>
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef> Name </th>
<td mat-cell *matCellDef="let element"> {{element.name}} </td>
</ng-container>
<ng-container matColumnDef="weight">
<th mat-header-cell *matHeaderCellDef> Weight </th>
<td mat-cell *matCellDef="let element"> {{element.weight}} </td>
</ng-container>
<ng-container matColumnDef="symbol">
<th mat-header-cell *matHeaderCellDef> Symbol </th>
<td mat-cell *matCellDef="let element"> {{element.symbol}} </td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
</div>
styles.css
table {
width: 100%;
}
We add the MatTableModule
to add the table.
Then in app.component.ts
, we add the table data in the ELEMENT_DATA
array.
The displayColumns
array has the column names.
In app.component.html
, we add the mat-table
directive to make the table Material Design style.
dataSource
has the data table’s data source.
The ng-container
components have the column definitions.
matColumnDef
have the columns.
The th
and td
are in the ng-container
and they’ll be shown in the table.
In styles.css
, we set the width
to 100%
to make the table fill the screen.
Expandable Rows
We can add expandable rows into our table.
For example, we can write:
app.component.ts
import { Component } from '@angular/core';
import { animate, state, style, transition, trigger } from '@angular/animations';
export interface PeriodicElement {
name: string;
position: number;
weight: number;
symbol: string;
}
const ELEMENT_DATA: PeriodicElement[] = [
{ position: 1, name: 'Hydrogen', weight: 1.0079, symbol: 'H' },
{ position: 2, name: 'Helium', weight: 4.0026, symbol: 'He' },
{ position: 3, name: 'Lithium', weight: 6.941, symbol: 'Li' },
{ position: 4, name: 'Beryllium', weight: 9.0122, symbol: 'Be' },
{ position: 5, name: 'Boron', weight: 10.811, symbol: 'B' },
];
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
animations: [
trigger('detailExpand', [
state('collapsed', style({ height: '0px', minHeight: '0' })),
state('expanded', style({ height: '*' })),
transition('expanded <=> collapsed', animate('225ms cubic-bezier(0.4, 0.0, 0.2, 1)')),
]),
],
})
export class AppComponent {
dataSource = ELEMENT_DATA;
columnsToDisplay = ['name', 'weight', 'symbol', 'position'];
expandedElement: PeriodicElement | null;
}
styles.css
table {
width: 100%;
}
tr.example-detail-row {
height: 0 !important;
}
tr.example-element-row:not(.example-expanded-row):hover {
background: whitesmoke;
}
tr.example-element-row:not(.example-expanded-row):active {
background: #efefef;
}
.example-element-row td {
border-bottom-width: 0;
}
.example-element-detail {
overflow: hidden;
display: flex;
}
.example-element-diagram {
min-width: 80px;
border: 2px solid black;
padding: 8px;
font-weight: lighter;
margin: 8px 0;
height: 104px;
}
.example-element-symbol {
font-weight: bold;
font-size: 40px;
line-height: normal;
}
.example-element-description {
padding: 16px;
}
.example-element-description-attribution {
opacity: 0.5;
}
app.component.html
<div>
<table mat-table [dataSource]="dataSource" multiTemplateDataRows
class="mat-elevation-z8">
<ng-container matColumnDef="{{column}}"
*ngFor="let column of columnsToDisplay">
<th mat-header-cell *matHeaderCellDef> {{column}} </th>
<td mat-cell *matCellDef="let element"> {{element[column]}} </td>
</ng-container>
<ng-container matColumnDef="expandedDetail">
<td mat-cell *matCellDef="let element"
[attr.colspan]="columnsToDisplay.length">
<div class="example-element-detail"
[@detailExpand]="element == expandedElement ? 'expanded' : 'collapsed'">
<div class="example-element-diagram">
<div class="example-element-position"> {{element.position}} </div>
<div class="example-element-symbol"> {{element.symbol}} </div>
<div class="example-element-name"> {{element.name}} </div>
<div class="example-element-weight"> {{element.weight}} </div>
</div>
</div>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="columnsToDisplay"></tr>
<tr mat-row *matRowDef="let element; columns: columnsToDisplay;"
class="example-element-row"
[class.example-expanded-row]="expandedElement === element"
(click)="expandedElement = expandedElement === element ? null : element">
</tr>
<tr mat-row *matRowDef="let row; columns: ['expandedDetail']"
class="example-detail-row"></tr>
</table>
</div>
We keep app.module.ts
the same as before.
In app.component.ts
, we add the detailExpand
animation to show an animation when we toggle the table row.
In app.component.html
, we added a new ng-container
with the matColumnDef
set to expandedDetail
.
It spans the whole table’s width.
The detailExpand
animation is used in this div.
The columns
property in the bottom is set to [‘expandedDetail’]
to add the detail column.
Conclusion
We can add basic tables and tables with expanded rows with Angular Material.