DEV Community

Cover image for expandable card in angular material using button.
ramtinmovahed
ramtinmovahed

Posted on

4

expandable card in angular material using button.

In this post, I'm going to implement a simple version of the expandable card with an action button in angular using angular material.
real deal
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 { }
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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';
  }
}
Enter fullscreen mode Exit fullscreen mode

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;
}
Enter fullscreen mode Exit fullscreen mode

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!

Image of Timescale

🚀 pgai Vectorizer: SQLAlchemy and LiteLLM Make Vector Search Simple

We built pgai Vectorizer to simplify embedding management for AI applications—without needing a separate database or complex infrastructure. Since launch, developers have created over 3,000 vectorizers on Timescale Cloud, with many more self-hosted.

Read more →

Top comments (2)

Collapse
 
muzafarali profile image
Ali • • Edited

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

Collapse
 
ramtinmovahed profile image
ramtinmovahed •

you should pass indexes to each card in the template and toggle them in a separate method in the typescript file.

Cloudinary image

Video API: manage, encode, and optimize for any device, channel or network condition. Deliver branded video experiences in minutes and get deep engagement insights.

Learn more

đź‘‹ Kindness is contagious

Immerse yourself in a wealth of knowledge with this piece, supported by the inclusive DEV Community—every developer, no matter where they are in their journey, is invited to contribute to our collective wisdom.

A simple “thank you” goes a long way—express your gratitude below in the comments!

Gathering insights enriches our journey on DEV and fortifies our community ties. Did you find this article valuable? Taking a moment to thank the author can have a significant impact.

Okay