Data Tables

Data tables display raw data sets. They usually appear in desktop enterprise products.

By default, the data tables will be responsive by allowing the user to scroll left/right when there is too much content to be viewed at once.

In react-md, data tables come in two types: plain and selectable where selectable is the default. A plain data table is not part of the material design specs and attempts to just add the base styles for a table and allow any sized content to be displayed. A selectable data table will inject checkboxes as the first column and allow each row to be selected.

If you are working with large data sets and have heavy table edit abilities, it is recommended to use a virtualization library such as react-virtualized instead of my tables. The html <table> is already pretty slow if you don't use fixed layouts and know the exact size of each cell beforehand. When all the event listeners and styles have been applied for the data table, you might start noticing performance issues around a 20x20 table. If a virtualization library isn't your thing, you can always try to paginate the results with the TablePagination component to limit the number of rendered rows/columns at a time

When a table has the plain prop enabled on tables, it will just set the min-height of each cell to the $md-data-table-plain-column-height, allow line wrapping, and centers the content vertically in the cell.

Lorem 1Lorem 2
consequat sunt aliquip ut reprehenderitsit esse reprehenderit laboris non
ut ex proident irure ipsumexcepteur id in nulla aliquip
mollit ex laboris consequat idculpa aliqua aliqua fugiat proident
dolore ad laborum ad addo quis est amet est
dolor sit Lorem ullamco cillumexercitation voluptate non ullamco nulla
commodo id aliquip Lorem laborumproident dolor veniam quis duis
labore tempor deserunt esse nullaenim dolor non cupidatat anim
dolore dolore non elit nullaest sint quis proident proident
non sunt amet sint inenim exercitation elit enim fugiat
commodo mollit enim nostrud nisisunt dolore commodo eiusmod anim

This example will showcase a selectable table. Checkboxes will be injected as the first cell into each row. To help with accessibility, the baseId prop is now required on the table so that each checkbox is updated with a unique id and a common name. Non-plain data tables have a height set to $md-data-table-column-height and prevent text wrapping.

You can also update the selectable table to be indeterminate which basically updates the "select all" checkbox to be in an "indeterminate" state when not all the rows have been checked.

Lorem 1Lorem 2
Lorem voluptate culpa mollit excepteureiusmod adipisicing cillum reprehenderit qui
non amet excepteur labore doesse enim voluptate et labore
anim reprehenderit qui ullamco irureofficia aliqua et ad irure
duis aliqua minim proident commodoaliquip sunt esse velit labore
amet consequat labore sunt inexcepteur do Lorem laboris ad
fugiat ex ipsum ea nisilaborum cillum commodo incididunt eu
anim culpa dolor duis reprehenderitaute minim ut minim id
eiusmod ut aliqua ullamco veniamut dolor labore ex anim
eiusmod voluptate dolor qui nostrudea occaecat occaecat sint aute
cupidatat excepteur consequat pariatur exexcepteur reprehenderit pariatur aliquip tempor

When you have large datasets, you can improve some of your app's performance by paginating your results and limiting the number of rows displayed at a time. This example shows how you can work with the TablePagination component and its API to easily accomplish this.

This component will be displayed at as a <tfoot> and attached to the bottom of the table. It will allow the user to paginate forwards or backwards by a preset number of rows. The default is to start at 10 rows per page and allows for 10, 20, 30, 40, 50, and 100 by default (both of these can be configured).

In addition, this example introduces a new styling prop: selectable. By default non-plain DataTables are selectable which means the checkbox will be automatically injected into the first cell of each row. Sometimes you want the styles of a non-plain DataTable but without the checkboxes. By disabling the selectable prop on each row, the non-plain styles will be applied and checkboxes will not be shown.

Column 1Column 2Column 3Column 4Column 5Column 6
amet non pariatur et duisculpa elit labore laborum elitsit dolor ad laboris magnaesse do exercitation excepteur autealiquip occaecat quis nulla cupidatatanim nostrud excepteur ex magna
ex ad voluptate minim adesse deserunt id veniam nonid aliquip deserunt fugiat consectetursit culpa laborum aliquip nisitempor qui sunt eu cillumenim sunt proident irure et
pariatur proident occaecat irure quisexercitation sint nisi duis officiaipsum dolore magna nostrud voluptateduis tempor veniam exercitation Loremquis consequat minim sunt eaconsequat enim ex mollit excepteur
et non quis consectetur elitsunt quis aliqua anim adest quis nisi eiusmod eiusmodproident qui ad sunt animad id culpa et adipisicingaliquip mollit duis occaecat nisi
magna cillum duis magna veniamullamco nostrud magna tempor nisienim dolor culpa laboris exoccaecat mollit amet ad sintnostrud voluptate consectetur dolor magnaculpa tempor eiusmod qui nostrud
ex excepteur in ea eiusmodenim ullamco cupidatat non esseconsequat ex dolore consequat eiusmodaute nostrud pariatur laboris sintconsectetur nulla reprehenderit eu estad sint qui voluptate nostrud
reprehenderit ea ut fugiat laborisut enim aliquip est quissunt minim officia officia ameteiusmod nisi ex sunt cillumea laboris ullamco reprehenderit adenim amet incididunt cillum quis
quis pariatur velit dolor etquis ipsum deserunt velit elitpariatur qui nisi Lorem laborumaliquip occaecat exercitation amet LoremLorem ea qui minim nostrudquis dolore tempor exercitation et
minim commodo officia aliqua commodofugiat enim pariatur velit nonmollit ut sunt enim dolorconsectetur deserunt est ipsum fugiatamet nostrud nulla veniam enimamet elit nulla eiusmod id
ut exercitation velit proident proidentea exercitation exercitation velit fugiatvelit veniam aliquip ipsum Loremea officia nulla qui incididuntconsequat non ullamco sunt inqui reprehenderit pariatur culpa do
Rows per page1-10 of 350

DataTables can become sortable by applying the sorted prop to one-to-many of the TableColumn that appear in the TableHeader. If the sorted prop is a boolean, it will inject a sort icon before the content in the column. When the sorted prop is true, it will assume that the content is sorted "ascending" while false will assume "descending". This will also update the column with the corresponding aria-sort value. You can then just add a simple onClick handler to your TableColumn to change the sort direction.

Conan the Barbarian1982
Conan the Destroyer1984
Jingle All The Way1986
Raw Deal1986
Red Sonja1985
Terminator 2: Judgement Day1991
Terminator 3: Rise of the Machines2003
Terminator Genisys2015
The 6th Day2000
The Last Stand2013
The Running Man1987
The Terminator1984
Total Recal1990

This example will show how you can create a table with editable content by using the additional table components: EditDialogColumn and SelectFieldColumn. Both of these components will attempt to stay within the viewport and automatically close if they are scrolled out of view while open. In addition, this example showcases another styling prop: grow.

When you have many columns in your DataTable and it is not a plain table, it is recommended to apply grow to one of your column headers. Due to how the html <table> automatically attempts to size each cell, you can end up the "Select All Checkbox" being offset from all the other cells. Enabling grow on one cell will allow it to fill all missing space in the table and only allow cells to be sized based on content and padding.

These two components utilize the baseId to automatically inject unique ids into each field. Each SelectField will gain an id of ${baseId}-${rowIndex}-${columnIndex}-select-field. Each EditDialogColumn will generate an id of ${baseId}-${rowIndex}-${columnIndex}-edit-dialog for the dialog and ${baseId}-${rowIndex}-${columnIndex}-edit-dialog-field for the field in the dialog. If these do not suit your needs, you can still override them manually as props.

The SelectFieldColumn is just a simple wrapper of a TableColumn and a SelectField but it does some work behind the scenes to work with the Layover component. All of the props are basically the same as the SelectField and can be used the same way.

For more information about the EditDialogColumn types, please see the next example.


Edit dialogs have some built in interactions for handling saves and keyboard support. By default, the value in the dialog is saved automatically whenever the dialog is closed with any interaction except for pressing the escape key or hitting the cancel button in large edit dialogs. So this means that if the user clicks somewhere else on the page, presses enter, or scrolls the page, the value will be saved. The dialog can be updated so that the cancel action happens if a user presses tab, clicks somewhere else on the page, or scrolls the page instead.

Edit Dialogs are a mainly desktop interface. Due to the weirdness in how different mobile devices handle keyboards, the dialog versions of the EditDialogColumn do not work on mobile devices. Use the inline mode stated below, or go for a better interface on mobile with a row card edit view.

The default EditDialog will just be a small dialog that displays a text field with minimal padding.

A large EditDialog will require a title prop to display above the text field and then create a footer including a cancel and ok button.

If you want to keep the UI simple, you can create inline edit dialogs which just display a text field in the cell instead of creating a dialog (so the EditDialog is sort of a bad name by this point). By default, a pencil icon will be added to the right side of the text field to indicate that it can be typed into (this can also be removed via props).

When the user tab-focuses the edit dialog column, the dialog will automatically be opened and the text field will be focused for text edits. If the user presses tab in an inline or non-large dialog, the dialog will be closed and the save interaction will be triggered (unless it is switched to do cancel on outside interactions described above). In any case, if the user presses the escape key, the dialog will be closed and the cancel action will be called. Since it is sometimes better to not automatically open the dialog immediately after tab-focus, the auto-open feature can be disabled by disabling visibleOnFocus so the user is required to press space or enter to open the edit dialog.

When the dialog is set to large, the tab interactions will be "trapped" within the dialog until the user selects the ok or cancel button (or presses enter on the text field). The dialog can still be closed by pressing the escape key to cancel any cell edits.

When the dialog is set to inline, tabbing will always save the data and pressing escape will call the cancel action.

The EditDialogColumn uses the TextField behind the scenes and correctly applies all the props to the text field. This means you can integrate help text, error messages, counters, multiline fields, etc for the this component as well.

Some Data

If you want to use menus within the DataTable, it is recommended to use the provided helper components to help out. Since the DataTable is responsive by default and allows for scroll bars, there can be some weird behavior without them since they use the Layover. The helper components automatically attempt to position themselves related to the DataTable as well as injecting unique ids like the other form inputs for the table. Check out the example below to see how to use the MenuButtonColumn and DropdownMenuColumn components.

The FlightScott Masterson
Room of PlatesAli Conners
The Sleek BootSandra Adams
Night HuntingJanet Perkins
Rain and CoffeePeter Calsson
Ocean ViewTrevor Hansen
Lovers on the RoofBritta Holt
Lessons from DelhiMary Johnson
MountaineersAbbey Christensen
Plains in the NightDavid Park
Dear OliviaSlyvia Sørensen
Driving LessonsHalimer Carver

There is some very limited support for fixed table headers/footers built into react-md. However, it is advisable to use a third party library such as react-virtualized when dealing with heavy interaction-based tables or using fixed headers. Part of the problem with the implementation that is built into this library is that the vertical scrollbar does not appear until you have scrolled horizontally to the end which is confusing for users on OSes that display scroll bars.

If this still seems fine, there is a mixin built in that will help you create fixed tables at a specific size or to span the entire page. See react-md-make-fixed-table for some more information there.

This example will show how you can use your fixed table headers/footers along with the TablePagination component to dynamically retrieve data from an API and display it in your table.

One of the use cases of tables is to have dynamic content that can be added or removed. There is a component built to help with this named the TableCardHeader which works well with the DataTable's selectable rows. The TableCardHeader was built to display an optional title and any children in a CardTitle component until it is toggled to a "contextual" view where another title and any additional actions can be displayed. A great example of this is when rows in the DataTable are selected and you would like to allow the user to delete them.

This example will show how you can integrate DataTables into Cards (with built in styling changes) and allow the user to add/remove rows from the table.

NOTE: One of the problems with the built-in checkbox support is that it uses React's context to push the changes down to each component. However if you ever use shouldComponentUpdate or a PureComponent, these changes won't be persisted to the child components since they block context updates. It is recommended to take full control instead.


Dessert (100g serving)TypeCaloriesFat (g)Carbs (g)Protein (g)Sodium (mg)Calcium (%)Iron (%)
Frozen yogurtIce cream159624487141
Ice cream sandwhichIce cream2379374.312981
Jelly beanOther37509405000