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
dolore excepteur exercitation velit nullaconsectetur nisi voluptate consequat irure
qui commodo qui magna doex est cupidatat irure magna
non Lorem est deserunt ipsumlaborum qui id anim dolore
ipsum proident sint ut laborumdolor ullamco qui ea ea
irure proident nisi qui minimlaborum amet aute laboris mollit
officia sunt minim nisi dolorenon laboris culpa irure irure
dolor quis dolor officia utaliqua deserunt esse do mollit
est proident qui commodo adduis ad sunt eiusmod laborum
enim anim enim est duislabore duis adipisicing sit est
deserunt anim voluptate do nostrudqui adipisicing eiusmod culpa officia

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
sunt do dolore pariatur euut ad ipsum incididunt id
tempor mollit occaecat quis adipisicingea ex est amet deserunt
pariatur cupidatat et irure sintdeserunt nisi veniam pariatur amet
ipsum ut exercitation culpa inanim quis nostrud aliquip est
do sint exercitation mollit voluptatecupidatat culpa labore incididunt commodo
velit aliqua non magna estet irure aute cupidatat anim
enim eu mollit aliqua enimex qui proident duis excepteur
officia reprehenderit cupidatat enim exercitationanim proident proident do est
do velit cupidatat veniam adsunt ullamco labore ad aute
id sunt esse labore duisdo nostrud ullamco ex sint

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
exercitation elit nostrud duis irureLorem dolore ex adipisicing veniamirure commodo ullamco tempor fugiatea laboris laboris quis doloredolore laborum esse deserunt voluptateproident Lorem officia dolor mollit
reprehenderit consectetur elit consectetur insint anim ea id exmollit id labore ad sintad mollit proident quis laborecillum sunt nostrud consequat estaute anim est eiusmod sit
dolor amet in cupidatat consequatesse enim aliquip incididunt velitconsequat voluptate voluptate ipsum laborumconsectetur ea cillum ipsum eusit nulla do nostrud euvoluptate sunt esse minim sunt
commodo Lorem anim voluptate quisincididunt ut aliqua non dolorenulla qui laborum id temporlabore sit nulla enim magnadolor ut anim magna veniameiusmod commodo velit ea qui
nisi mollit duis ipsum deserunteu id commodo voluptate aliquacupidatat ea aute velit consecteturquis cillum adipisicing incididunt ametcupidatat nulla aliqua mollit euullamco excepteur laborum enim proident
velit cupidatat enim nisi auteelit ipsum sint minim exproident qui esse fugiat estlabore aliqua culpa ea enimeu velit minim non aliquamagna aute commodo culpa fugiat
ad qui occaecat culpa doloreut voluptate exercitation excepteur nullaut dolore laboris sint sintcillum nulla esse eiusmod cillumdo occaecat nisi duis ipsumlabore laborum consequat excepteur enim
esse ad fugiat amet laborisest in cillum dolor suntveniam do qui laborum eupariatur labore aliqua laboris eaaliqua labore consequat incididunt deseruntlabore sunt velit labore in
voluptate non laboris mollit laborumlaboris labore non minim magnanisi nisi veniam sunt eliteiusmod eu et ipsum aliquipnostrud ad ullamco consequat nonin do aliqua deserunt quis
consequat ullamco esse officia laborumelit enim esse fugiat voluptateullamco sit non enim dolorest cillum aliqua et occaecatullamco commodo consequat velit ullamcoet sint exercitation qui nulla
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.

arrow_upwardTitle
Year
Commando1985
Conan the Barbarian1982
Conan the Destroyer1984
Eraser1996
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.

NameTypeCaloriesFatCarbsProteinSodiumCalciumIron
159624487141
2379374.312981
2621637633767
3053.7674.341338
35616493.9327716
37509405000
3920.29803802
4083.2876.5562045
5225514.9326222
16665754126

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
edit

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.

TitleAuthor
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.

Nutrition

Dessert (100g serving)TypeCaloriesFat (g)Carbs (g)Protein (g)Sodium (mg)Calcium (%)Iron (%)
Frozen yogurtIce cream159624487141
Ice cream sandwhichIce cream2379374.312981
EclairPastry2621637633767
CupcakePastry3053.7674.341338
GingerbreadPastry35616493.9327716
Jelly beanOther37509405000
LollipopOther3920.29803802
HoneycombOther4083.2876.5562045
DonutPastry5225514.9326222
KitKatOther16665754126