Angular Material card clickable

Viewed 29835

I want to add a routerlink to a mat-card component to make card clickable. My component is like this:

<mat-card class="card" >
     <mat-card-content>
          <mat-card-title> {{title}}</mat-card-title>
          <mat-card-subtitle> {{subtitle}} </mat-card-subtitle>
     </mat-card-content>
</mat-card>

How to accomplish this?

Thanks.

5 Answers

simply use the routerLink

<mat-card-content  routerLink = "path">
<mat-card (click)="doStuff()" class="card" >
     <mat-card-content>
          <mat-card-title> {{title}}</mat-card-title>
          <mat-card-subtitle> {{subtitle}} </mat-card-subtitle>
     </mat-card-content>
</mat-card>

Then it should handle the click

If you need to any operations before navigate.Best Practices is use click method for handling any operations and navigate,

Html

<mat-card class="card" (click)="navigate()">
     <mat-card-content>
          <mat-card-title> {{title}}</mat-card-title>
          <mat-card-subtitle> {{subtitle}} </mat-card-subtitle>
     </mat-card-content>
</mat-card>

Ts

import { Router } from '@angular/router';

constructor(private router:Router){
}
navigate(){
//do your any operations
this.router.navigate(['path']);
//also you can pass like this,
 this.router.navigateByURL(['path']);
}

If you have dynamic route, you can use [routerLink] directive like below:

We reach title with event binding. You can mix dynamic values with static values as well.

For example if we have a variable named team in our component with the property id, we can define a path like below:

[routerLink]="['/teams', 'edit', team?.id]"

In this example the first and second value of the array '/teams' and 'edit' are static and team?.id is dynamic which we reach with event binding.

And it can be translated in the browser like: /teams/edit/3

<mat-card class="card" [routerLink]="[title] >
  <mat-card-content>
       <mat-card-title> {{title}}</mat-card-title>
       <mat-card-subtitle> {{subtitle}} </mat-card-subtitle>
  </mat-card-content>
</mat-card>

Please don't forget about accessibility. You're basically turning the card into a button. So you need to tell assistive devices that it is a button. Check out the ARIA Authoring Practices Guide button examples

You also need to add the default button event bindings (click, space key, enter key). If you're using a router, you may need to follow Karnan Muthukumar's advice and handle the router navigation in the TypeScript instead of HTML so you can have the necessary event bindings.

<mat-card role="button" tabindex="0" class="is-focusable"
    (click)="cardEventHandler() 
    (keydown.enter)="cardEventHandler()" 
    (keydown.space)="cardEventHandler(); $event.preventDefault()">

    <mat-card-title> {{title}} </mat-card-title>
    <mat-card-subtitle> {{subtitle}} </mat-card-subtitle>
    <mat-card-content>  {{content}} </mat-card-content>

</mat-card>

Note: The space key event binding may cause the window to scroll if you don't account for the default space key behavior. Using keydown.space instead of keyup.space helps prevent the default behavior before it happens. You can use preventDefault() in the HTML, or pass the $event to your method and use preventDefault() in your method.

The .is-focusable class adds a pointer cursor and focus-visible pseudo-class to provide custom focus state styling.

.is-focusable {
  cursor: pointer;
}

.is-focusable:focus-visible {
  outline: none;
  background-color: #efefef;
  box-shadow: 0 3px 5px -1px #0003, 0 6px 10px #00000024, 0 1px 18px #0000001f;
}

Of course, you can handle styling however you like, as long as you don't remove all focus styling (default or custom) and keep keyboard users from knowing when the card is focused.

Related