Building a reusable and configurable table with Angular Material 15
Tags: angular, material, table, webdev
Published: 2023-01-16 09:51:18

The `mat-table` in Angular Material provides a data-table that can be used to display rows of data, but it is not reusable and leads to a lot of code duplication.

Therefore there is a possibility to build your own **reusable** generic table on its basis, with optionally **configurable pagination, filtering, sorting, columns and row actions**, just using Angular and Material Design.


## Table component

### Column interface

First of all, we have to define the column interface, in order to pass the column information to the table from a parent component:

{% embed https://gist.github.com/dnlrbz/d9cc6e5b6eff861ac39f582055765bb4 %}

### Table

Secondly, we create our reusable table component with `ng generate component table` command, and define _configurable input and output paramaters_ in the .ts file, which are being passed from parent component.

### Input from the parent component:

- `isPageable`: should the table have pagination?
- `isSortable`: should the table have sorting?
- `isFilterable`: should there be a filter, operating on the whole table?
- `tableColumns`: columns of type interface TableColumn👆🏻 with parameters (name, dataKey, position, isSortable)
- `rowActionIcon`: name of the mat-icon, that is going to be embedded in each row.
- `paginationSizes`: options for rows number on a page
- `defaultPageSize`: default number of rows on a page
- `tableData`: the actual data, which must have a setter, to dynamically get changes of the from parent component (e.g. after sorting it in parent). If we want to apply pipes or services on this data, we should do it in the parent component beforehand, and pass the “ready to display” data in the table.


### Output events to the parent component:

- `sort`: Outputs the key to sort with, and the direction(ascending, descending). The sorting logic must be implemented in the parent component, in order to keep the table abstract and simple. Moreover, sorting of different datatypes, e.g. Date and string has different logic, and it is impossible to foresee all sorting strategies in the table.
- `rowAction`: Outputs the whole row, when a user clicks on the action-icon in the given row.

{% embed https://gist.github.com/dnlrbz/28c8df70e7d280d7ce006a273463aead %}

### Table template

Thirdly, we define a template for the table component, and make almost everything optional with `*ngIf` directive, for instance: filter, row-action, sorting and pagination:

{% embed https://gist.github.com/dnlrbz/28d38fc4e6f95b693e93a7c0319b0bb9 %}

### Example

We have created `customers-table` and `orders-table` components, which use our generic table component and pass data to it.

`customers-table` component only uses basic table features, therefore it only passes the data array and columns definition to the table.

{% embed https://gist.github.com/dnlrbz/ee917e6649656a8912f60a008968eb90 %}


`orders-table` uses all features of table and explicitly passes all optional parameters, to turn on the pagination, filtering and sorting.

{% embed https://gist.github.com/dnlrbz/f85a87430681b1d013a16700fc4aacbf %}

## Complete code

{% embed https://github.com/dnlrbz/angular-material %}