Wrapping Angular Material Table: Styling it once & Drag+Drop Sorting

The development of Vendasta’s Material Styled Tables

Mitchell Woodhouse Mckenzie
Vendasta
4 min readMay 14, 2019

--

At Vendasta, we have moved most of our legacy projects away from a previous frontend framework to Angular using Angular Material as the base for our styles. While Angular Material satisfies most of our needs for interaction, we want to have a consistent look and feel across our platform that conforms with Vendasta’s visual identity. Below is an example of Angular Material’s default style for tables:

Angular Material default table — https://material.angular.io/components/table/overview

After a slight style change, this is the table we ended up with:

Angular Material Table — Slightly Stylized

With the table now styled, we could copy & paste the styles or copy the stylesheet everywhere we may need it. However, neither of these options satisfy the following requirements:

  • A single place to update the style and have all the tables update their style
  • A simple method for our UX/UI co-workers to update the styles

Creating a component in our Shared Library

In the end I created a component in a library that is shared between all of our frontend projects. It ended up being quite a simple component with the va-mat-table.component.html looking like this:

You can ignore the action-bar section of the component as we will cover that later on in this article. The main thing to focus on is the ng-content (line 4) as that is where the table is outputted. Doing it this way we can have a single va-mat-table.component.scss which styles the table itself without limiting use of the Material Table. The component does not have any knowledge of the table, all it needs to know is that it has to render something in the ng-content section. Using this component is very simple:

Now when the table is rendered, it is set up completely in the parent component and only uses va-mat-table for the styles of the table.

Ability to wrap any existing or new table at Vendasta

With the way the table is created, we can wrap any existing Material table with va-mat-table and it will automatically be styled the way we want our tables at Vendasta.

Adding in the ability to pass in anything to our tables action bar

Since we are sharing a component between all of our tables, it would be the perfect spot to add in more functionality so all the tables could possibly benefit. Remember the following line from the va-mat-table.component.html:

This is how we are going to be able to add more functionality to the tables. Since we can tag multiple ng-content using the select attribute (https://medium.freecodecamp.org/everything-you-need-to-know-about-ng-template-ng-content-ng-container-and-ngtemplateoutlet-4b7b51223691 if you want to read more on ng-content) we are able to do something like this:

Now anything that we pass in between <ng-container action-bar-items> will be rendered in the <div class="action-bar"> in our va-mat-table.component.html

Text passed in to the Action Bar of the Table

Adding Drag and Drop sorting to the table

A feature that is requested on many of our tables is the ability to sort and toggle the columns, so adding it as something that is available to our tables makes sense.

Drag and Drop sorting and ability to toggle columns on and off

In our va-mat-table component I added a new folder called actions where any shared actions between the tables will live. In that folder I created a new component called column-sorter which is a regular Angular component. Its selector looks like:

which will look for something like:

Implementing the dragging and dropping of the columns is actually quite a simple process. Using the built-in Angular CDK for the dragging and dropping and Angular Material Menu for the menu functionality gives us a solid base. The most important section in the component is the Input and Outputs:

This allows us to do [(columns)]="displayedColumns" which supplies the initial state of the columns and emits an event when the columns are reordered/toggled. When the even it emitted it updates displayedColumns which reorders the columns of the table. It doesn’t have to be called displayedColumns it is just the array of strings that you passed to matHeaderRowDef and matRowDef (refer to https://stackblitz.com/angular/oddkdyrgdyn?file=app%2Ftable-basic-example.ts for how the variable displayedColumns works).

Now if we add it the to action bar it would look like this:

The table with the drag and drop menu open

A Live example to view of the table

If you made it this far in the article, you probably are looking for a live example. Below is a live example of what the table should look like:

Conclusion

This may not be the end-all perfect solution but it solves a need within our organization for our frontend story. Using this solution we have minimal code duplication and consistent styles across our platform!

--

--