Wanna give users their choice of what kinds of actions they take on a data table row? If so, then consider adding clickable icons to your Angular Material table.

And, happily enough, I'm here to show you how to make it happen.

Of course, you can always go straight to the code on GitHub. But there's a lot going on there.

Remember: if you're having problems running the Angular app locally, be sure to check the README.

Please note: this guide is a part of an ongoing series of tutorials on how to create a customer relationship management (CRM) application from scratch. The GitHub code for each guide belongs to a specific branch. The master branch holds the entire application up to the current date. If you want to follow the whole series, just view the careydevelopmentcrm tag. Note that the website displays the guides in reverse chronological order so if you want to start from the beginning, go to the last page.

The Business Requirements

Your boss Smithers walks into your office, clearly frustrated.

"Welp, management changed their minds again!" he says, throwing his hands up in the air. "It's about that CRM app you're working on. They don't want clickable rows in that table any more! They want clickable icons!"

Smithers huffs.

"Can you put a couple of icons in each row of the contacts table? Make one icon for editing the contact and another for just viewing the contact."

He walks out, muttering to himself about his boss's boss.

A Good Starting Point

As Smithers mentioned, you've already got a table that shows all contacts in your CRM. A while back, you updated the table so users can edit the contact by just clicking on that contact's row.

But now management has some new ideas.

So you're going to create a new column that shows icons. Make it the first column in the table so it's easy for users to find it.

In that column, you'll show two icons: one for viewing the contact and one for editing the contact.

Now that you know the requirements, let's get started.

A New Column!

Even though your table is horizontally scrollable, it's going to get too "busy" if you just throw another column in there. Eliminate one column and add a new column called "Action." That's where you'll put the icons.

Update view-contacts.component.html. Add this nugget in the <table> element:

<ng-container matColumnDef="action">
  <tr><th mat-header-cell *matHeaderCellDef> Action </th></tr>
    <td mat-cell *matCellDef="let row" style="width:20%">
      <button mat-icon-button color="primary" (click)="viewContact(row)" title="View Contact"><mat-icon>preview</mat-icon></button>
      <button mat-icon-button color="primary" (click)="editContact(row)" title="Edit Contact"><mat-icon>edit</mat-icon></button>

That's the column that will display your new clickable icons. 

First of all, note what's not in that code block: mat-sort-header.  That's because you don't need to sort the Action column.

I mean, why would you want to?

Anyhoo, the important stuff is inside the <td> element. Those are the two clickable icons, here coded as buttons.

They both use Angular Material icons so everything plays nicely with the underlying framework.

The first button follows the logic in the viewContact() method when clicked. The second method follows the logic in editContact().

You haven't yet implemented those methods. I'll cover that in a moment.

In the meantime, that's all you need to do on the HTML side.

Coding the Component

Next, edit view-contacts.component.ts. Make a couple of changes, starting with this one:

  displayedColumns: string[] = ['action', 'lastName', 'firstName', 'status', 'title', 'company'];

The update there is that the array removes 'source' and adds 'action.'

Remember: 'action' is the column you just created. So you certainly want that included.

But the table seems too cluttered with 'source' in there. So take it out.

Next, you need to implement those two methods referenced in the clickable icons:

  editContact(contact: Contact) {
    let route = '/contacts/edit-contact';
    this.router.navigate([route], { queryParams: { id: contact.id } });

  viewContact(contact: Contact) {
    let route = '/contacts/view-contact';
    this.router.navigate([route], { queryParams: { id: contact.id } });

Come to think of it, you had already implemented editContact() in the guide on clickable rows. So that's done.

So all you really needed to do was implement viewContact(). It follows the exact same logic as editContact() except it uses a different URL.

And bam. There you have it.

Investigating the Icons

Now it's time to see if this thing really works.

Save all your files and start your Angular CRM app. Make sure you also start the corresponding Spring Boot applications: the user service and the contact service.

Now visit http://localhost:4200/login and login with the usual credentials (darth/thedarkside).

Select Contacts and View Contacts from the left-hand sidebar menu.

You should see a table listing all your contacts. But now it has clickable icons in the left-most column.


Go ahead and click the preview icon (the one on the left). You should go to a different route that shows read-only info about the contact.


Now go back to the table and click the edit icon (the pencil). You should see an editable form.


Bingo. You did it.

Wrapping It Up

Now that you get the idea, it's over to you.

Update the code you see here to suit your own business requirements. Or maybe add another icon.

How about a delete icon?

Or just feel free to go grab the source code on GitHub.

Have fun!

Photo by Domenico Gentile on Unsplash