In this post, I'm going to implement a simple version of the expandable card with an action button in angular using angular material.
material design
Step 1: base initializations
create a new angular project by running
ng new my-app
we just need the basic functionalities for this demo, so we don't need routing and strict mode.
Then, install angular material by running:
ng add @angular/material
don't forget to enable the browser animations
next, delete the content of app.component.html
Step 2: Import the necessary modules
Based on material design, to implement, we need three components: card, divider, and button.
so in app.module.ts add them to the imports array
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { MatCardModule } from '@angular/material/card';
import { MatButtonModule } from '@angular/material/button';
import { MatDividerModule } from '@angular/material/divider';
@NgModule({
declarations: [
AppComponent,
],
imports: [
BrowserModule,
BrowserAnimationsModule,
MatCardModule,
MatButtonModule,
MatDividerModule,
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
Step 3: change the template
edit the app.component.html
<mat-card class="card">
<mat-card-header>
<mat-card-title>Title</mat-card-title>
<mat-card-subtitle>Subtitle</mat-card-subtitle>
</mat-card-header>
<mat-card-content>
<p>
Lorem ipsum, dolor sit amet consectetur adipisicing elit. Exercitationem, praesentium sit tempora numquam vel odit
dolorem qui quod sint distinctio! Quasi exercitationem tempore voluptas quam voluptatibus distinctio ex magni
repellendus?
</p>
<p [@bodyExpansion]="state" class="expandable-content">
[expandable] Lorem ipsum, dolor sit amet consectetur adipisicing elit. Exercitationem, praesentium sit tempora
numquam vel odit
dolorem qui quod sint distinctio! Quasi exercitationem tempore voluptas quam voluptatibus distinctio ex magni
repellendus?
</p>
<mat-divider>
</mat-divider>
</mat-card-content>
<mat-card-actions>
<button mat-button (click)="toggle()" color="primary">EXPAND</button>
</mat-card-actions>
</mat-card>
the bodyExpansion is the name of the animation that we're going to implement next.
We needed to add the mat-divider component as specified in the material design spec.
The state is the name of the property that's responsible for the state of the animations
the toggle method will change this state (as you guest)
Step 4: adding the animations and implementing toggle method
change the content of app.component.ts
import { trigger, state, style, transition, animate } from '@angular/animations';
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
animations: [
trigger('bodyExpansion', [
state('collapsed, void', style({ height: '0px', visibility: 'hidden' })),
state('expanded', style({ height: '*', visibility: 'visible' })),
transition('expanded <=> collapsed, void => collapsed',
animate('225ms cubic-bezier(0.4, 0.0, 0.2, 1)')),
])
]
})
export class AppComponent {
title = 'my-app';
state = 'collapsed';
toggle(): void {
this.state = this.state === 'collapsed' ? 'expanded' : 'collapsed';
}
}
In the animations array, we defined our animation. The trigger name is bodyExpansion that should match the trigger name that we set in the template. It has two states, collapsed and expanded. The collapsed state defines how the component should look when it's not expanded. So the height is zero and it's hidden.
The expanded state defines how it should look when it's expanded. So the height would be the actual height and it should be visible.
The transition defines how to move between these two states. the void=>collapsed
is there to ensure it's collapsed when the component first renders.
The toggle method will change the state property that we defined above.
Final step: add the appropriate styles
In the app.component.css , add the following code
.card {
width: 500px;
margin: 50px auto auto auto;
}
.expandable-content {
overflow: hidden;
}
The thing to note here is the expandable-content
class. This class makes the final fixes to the smooth transition.
Hope this was useful, have a nice day!
Top comments (2)
useful article on expandable, I make and it's work with one card if we need to apply on multiple cards then it expands and collapses all card with one click.
I'm looking for dynamic expand/collapse with multiple cards
you should pass indexes to each card in the template and toggle them in a separate method in the typescript file.