import DataGrid from '@concur/nui-widgets/lib/DataGrid/DataGrid';
Data grids are used for displaying tabular data and providing ways to interact with that data. Built using semantic table markup, data grids support common table/grid functionality such as sorting, row selection, expandable rows, summary rows, alternate row striping, custom cell rendering, etc. The DataGrid
component does not do a number of the functions noted, but rather provides the common UI for the component and provides callback functions for the consumer to control the other features.
Although the DataGrid
itself doesn’t support horizontal scrolling, you can achieve a horizontal scrolling effect by wrapping it in a <div>
with a class specifying the appropriate overflow behavior.
There are three supported grid sizes: 'lg'
, 'md'
(the default), and 'sm'
. Use the size
property to set the appropriate size.
const userDataHIG = [
{uid: 1, jersey: 12, last: 'Brady', first: 'Tom', email: 'Tom.Brady@patriots.com', birthday: '1977-09-14', isAwesome: false},
{uid: 2, jersey: 3, last: 'Wilson', first: 'Russell', email: 'Russell.Wilson@seahawks.com', birthday: '1990-11-02', isAwesome: true},
{uid: 3, jersey: 9, last: 'Brees', first: 'Drew', email: 'Drew.Brees@saints.com', birthday: '1979-02-10', isAwesome: true},
{uid: 4, jersey: 2, last: 'Ryan', first: 'Matt', email: 'Matt.Ryan@falcons.com', birthday: '1988-03-25', isAwesome: true},
{uid: 5, jersey: 1, last: 'Newton', first: 'Cam', email: 'Cam.Newton@panthers.com', isAwesome: false}
];
const sortedData = Sorters.numeric(userDataHIG, 'uid', true);
const HIGDataGridEx01 = () => (
<div className='row'>
<div className='col-xs-12 col-md-5'>
<DataGrid
caption={{
title: 'Player jersey numbers'
}}
columns={[
{propertyName: 'jersey', headerContent: 'Number'},
{propertyName: 'first', headerContent: 'First Name'},
{propertyName: 'last', headerContent: 'Last Name'}
]}
data={sortedData}
empty={<DataGrid.Empty title='No users found' />}
size='lg' />
</div>
<div className='col-xs-12 col-md-4'>
<DataGrid
caption={{
title: 'Player jersey numbers'
}}
columns={[
{propertyName: 'jersey', headerContent: 'Number'},
{propertyName: 'first', headerContent: 'First Name'},
{propertyName: 'last', headerContent: 'Last Name'}
]}
data={sortedData}
empty={<DataGrid.Empty title='No users found' />} />
</div>
<div className='col-xs-12 col-md-3'>
<DataGrid
caption={{
title: 'Player jersey numbers'
}}
columns={[
{propertyName: 'jersey', headerContent: 'Number'},
{propertyName: 'first', headerContent: 'First Name'},
{propertyName: 'last', headerContent: 'Last Name'}
]}
data={sortedData}
empty={<DataGrid.Empty title='No users found' />}
size='sm' />
</div>
</div>
);
Columns can be made sortable. Sortable column headers appear as links. The currently sorted column shows the directional arrow (up for ascending and down for descending). Use the sorting
property to enable sorting.
If the consumer does not wish to manage sorting, DataGrid
will handle it by default. For each sortable column, either set the isSortable
property or the sorter
property. There are some convenience sort functions in the Sorters utility for numbers, strings and dates. If no sorter
property is specified, the default case-insensitive sort will be used. Built-in sorting should only be used when the entire dataset is passed.
const userDataHIG = [
{uid: 1, jersey: 12, last: 'Brady', first: 'Tom', email: 'Tom.Brady@patriots.com', birthday: '1977-09-14', isAwesome: false},
{uid: 2, jersey: 3, last: 'Wilson', first: 'Russell', email: 'Russell.Wilson@seahawks.com', birthday: '1990-11-02', isAwesome: true},
{uid: 3, jersey: 9, last: 'Brees', first: 'Drew', email: 'Drew.Brees@saints.com', birthday: '1979-02-10', isAwesome: true},
{uid: 4, jersey: 2, last: 'Ryan', first: 'Matt', email: 'Matt.Ryan@falcons.com', birthday: '1988-03-25', isAwesome: true},
{uid: 5, jersey: 1, last: 'Newton', first: 'Cam', email: 'Cam.Newton@panthers.com', isAwesome: false}
];
class HIGDataGridEx02 extends React.Component {
constructor(props) {
super(props);
this.state = {
data: userDataHIG
};
}
render() {
return (
<div>
<DataGrid
caption={{
title: 'Player jersey numbers and birthdays'
}}
columns={[
{propertyName: 'jersey', headerContent: 'Number', sorter: Sorters.numeric},
{propertyName: 'first', headerContent: 'First Name'},
{propertyName: 'last', headerContent: 'Last Name', isSortable: true},
{
propertyName: 'birthday',
headerContent: 'Birthday',
emptyCellLabel: 'Birthday not provided',
sorter: Sorters.date
}
]}
data={this.state.data}
empty={<DataGrid.Empty title='No users found' />}
sorting={{
propertyName: 'last',
asc: true
}} />
</div>
);
}
}
If the consumer wants to manage sorting, they must manage it for all sortable columns. Use the onSort
property in sorting
to define the callback function that will handle the sorting. Use of the onSort
property will supersede any column sorter
properties. Use the data
property to pass the sorted data. Use the sorting
property to pass updated state for sort column and direction. There are some convenience sort functions in the Sorters utility for numbers, strings and dates. Use the isSortable
to mark each sortable column. This method of sorting is likely needed when only a partial dataset is passed.
const userDataHIG = [
{uid: 1, jersey: 12, last: 'Brady', first: 'Tom', email: 'Tom.Brady@patriots.com', birthday: '1977-09-14', isAwesome: false},
{uid: 2, jersey: 3, last: 'Wilson', first: 'Russell', email: 'Russell.Wilson@seahawks.com', birthday: '1990-11-02', isAwesome: true},
{uid: 3, jersey: 9, last: 'Brees', first: 'Drew', email: 'Drew.Brees@saints.com', birthday: '1979-02-10', isAwesome: true},
{uid: 4, jersey: 2, last: 'Ryan', first: 'Matt', email: 'Matt.Ryan@falcons.com', birthday: '1988-03-25', isAwesome: true},
{uid: 5, jersey: 1, last: 'Newton', first: 'Cam', email: 'Cam.Newton@panthers.com', isAwesome: false}
];
class HIGDataGridEx03 extends React.Component {
constructor(props) {
super(props);
this.sortingProp = 'jersey';
this.sortAsc = true;
this.state = {
data: Sorters.numeric(userDataHIG, this.sortingProp, this.sortAsc)
};
}
_sort = (prop) => {
if (prop === this.sortingProp) {
this.sortAsc = !this.sortAsc;
} else {
this.sortAsc = true;
this.sortingProp = prop;
}
// Do the sorting now
if (prop === 'uid' || prop === 'jersey') {
this.setState({ data: Sorters.numeric(this.state.data, prop, this.sortAsc)});
} else if (prop === 'birthday') {
this.setState({ data: Sorters.date(this.state.data, prop, this.sortAsc)});
} else {
this.setState({ data: Sorters.caseInsensitive(this.state.data, prop, this.sortAsc)});
}
}
render() {
return (
<div>
<DataGrid
caption={{
title: 'Players',
summary: 'First column is jersy number, next two are name, last is birthday'
}}
columns={[
{propertyName: 'jersey', headerContent: 'Number', isSortable: true},
{propertyName: 'first', headerContent: 'First Name'},
{propertyName: 'last', headerContent: 'Last Name', isSortable: true},
{
propertyName: 'birthday',
headerContent: 'Birthday',
emptyCellLabel: 'Birthday not provided',
isSortable: true
}
]}
data={this.state.data}
empty={<DataGrid.Empty title='No users found' />}
sorting={{
propertyName: this.sortingProp,
asc: this.sortAsc,
onSort: this._sort
}} />
</div>
);
}
}
Any custom content can be rendered in the table cells. The callback functions can return any renderable content. The example below shows simple string concatenation, custom components and content to be wrapped in <td>
or <th>
elements. The DataGrid
component will handle the creation of the wrapping <td>
(table body) or <th>
(table header) elements. Use the bodyContent
column property to do custom cell rendering. Use the headerContent
column property and pass a function to do custom header cell rendering. If there are additional attributes to apply to the table cells, use the bodyProps
and/or headerProps
column properties.
const userDataHIG = [
{uid: 1, jersey: 12, last: 'Brady', first: 'Tom', email: 'Tom.Brady@patriots.com', birthday: '1977-09-14', isAwesome: false},
{uid: 2, jersey: 3, last: 'Wilson', first: 'Russell', email: 'Russell.Wilson@seahawks.com', birthday: '1990-11-02', isAwesome: true},
{uid: 3, jersey: 9, last: 'Brees', first: 'Drew', email: 'Drew.Brees@saints.com', birthday: '1979-02-10', isAwesome: true},
{uid: 4, jersey: 2, last: 'Ryan', first: 'Matt', email: 'Matt.Ryan@falcons.com', birthday: '1988-03-25', isAwesome: true},
{uid: 5, jersey: 1, last: 'Newton', first: 'Cam', email: 'Cam.Newton@panthers.com', isAwesome: false}
];
const EmailLink = ({email}) => (
<Link
href={`mailto:${email}`}
onClick={ (event) => event.stopPropagation() }>
{email}
</Link>
);
const HeaderIcon = () => (
<Icon ariaLabel='header icon label' iconName='star-empty' />
);
class HIGDataGridEx05 extends React.Component {
constructor(props) {
super(props);
this.state = {
data: userDataHIG
};
}
_renderJersey = (data) => {
return ('#' + data.jersey);
}
_renderName = (data) => {
return (data.first + ' ' + data.last);
}
_renderEmail = (data) => {
return (<EmailLink {...data} />);
}
_renderBirthday = (data) => data.birthday
_renderIcon = (data) => {
const isAwesome = data.isAwesome ? 'star' : 'star-empty';
return (<Icon ariaLabel='icon for isAwesome' iconName={isAwesome} />);
}
render() {
return (
<div>
<DataGrid
caption={{
title: 'Player jersy numbers',
summary: 'Includes column indicating awesome status'
}}
columns={[
{propertyName: 'jersey', headerContent: 'Jersey', bodyContent: this._renderJersey},
{propertyName: 'last', headerContent: <span><Icon ariaHidden iconName='user' /> Name</span>, bodyContent: this._renderName},
{propertyName: 'email', headerContent: 'Email Address', bodyContent: this._renderEmail},
{
propertyName: 'birthday',
headerContent: 'Birthday',
emptyCellLabel: 'Birthday not provided',
bodyContent: this._renderBirthday
},
{propertyName: 'isAwesome',
headerContent: <HeaderIcon />, headerProps: {className: 'reporttable-cell-icon'},
bodyContent: this._renderIcon, bodyProps: {className: 'reporttable-cell-icon'}
}
]}
data={this.state.data}
empty={<DataGrid.Empty title='No users found' />} />
</div>
);
}
}
Selectable rows allows multiple rows within a table to be selected (checked) at the same time. This is typically used when a single action will be performed to multiple items at once. When using selectable rows, an additional column will be added to render the selection checkbox for rows and in the header for selecting all rows. Use the selection
property to enable selectable rows.
const userDataHIG = [
{uid: 1, jersey: 12, last: 'Brady', first: 'Tom', email: 'Tom.Brady@patriots.com', birthday: '1977-09-14', isAwesome: false},
{uid: 2, jersey: 3, last: 'Wilson', first: 'Russell', email: 'Russell.Wilson@seahawks.com', birthday: '1990-11-02', isAwesome: true},
{uid: 3, jersey: 9, last: 'Brees', first: 'Drew', email: 'Drew.Brees@saints.com', birthday: '1979-02-10', isAwesome: true},
{uid: 4, jersey: 2, last: 'Ryan', first: 'Matt', email: 'Matt.Ryan@falcons.com', birthday: '1988-03-25', isAwesome: true},
{uid: 5, jersey: 1, last: 'Newton', first: 'Cam', email: 'Cam.Newton@panthers.com', isAwesome: false}
];
class HIGDataGridEx04 extends React.Component {
constructor(props) {
super(props);
this.state = {
data: Sorters.numeric(userDataHIG, 'jersey', true),
selectedRows1: [],
selectedRows2: [1, 3]
};
}
_isSelectable = (row) => {
return row.uid % 2;
}
_getSelectedRows = (selected, isSelectable) => {
let {
data
} = this.state;
let selectedRows = [];
if (selected) {
data.forEach((row) => {
selectedRows = toggleRowState(selectedRows, row.uid, isSelectable(row));
});
}
return selectedRows;
}
render() {
return (
<div className='row'>
<div className='col-xs-12 col-sm-6'>
<DataGrid
caption={{
title: 'Player jersey numbers'
}}
columns={[
{propertyName: 'jersey', headerContent: 'Number'},
{propertyName: 'first', headerContent: 'First Name'},
{propertyName: 'last', headerContent: 'Last Name'}
]}
data={this.state.data}
empty={<DataGrid.Empty title='No users found' />}
rowKey='uid'
selection={{
isSelected: (row, rowKey) => {
return this.state.selectedRows1.indexOf(rowKey) >= 0;
},
onSelectRow: (row, selected, rowKey) => {
let {
selectedRows1
} = this.state;
this.setState({
selectedRows1: toggleRowState(selectedRows1, rowKey, selected)
});
},
onSelectAll: (selected) => {
this.setState({
selectedRows1: this._getSelectedRows(selected, () => {
return true;
})
});
},
textSelect: 'Select row',
textSelected: 'Selected',
textSelectAll: 'Select all rows',
textUnselect: 'Unselect row',
textUnselectAll: 'Unselect all rows'
}} />
</div>
<div className='col-xs-12 col-sm-6'>
<DataGrid
caption={{
title: 'Player jersey numbers'
}}
columns={[
{propertyName: 'jersey', headerContent: 'Number'},
{propertyName: 'first', headerContent: 'First Name'},
{propertyName: 'last', headerContent: 'Last Name'}
]}
data={this.state.data}
empty={<DataGrid.Empty title='No users found' />}
rowKey='uid'
selection={{
isSelectable: this._isSelectable,
isSelected: (row, rowKey) => {
return this.state.selectedRows2.indexOf(rowKey) >= 0;
},
onSelectRow: (row, selected, rowKey) => {
let {
selectedRows2
} = this.state;
this.setState({
selectedRows2: toggleRowState(selectedRows2, rowKey, selected)
});
},
onSelectAll: (selected) => {
this.setState({
selectedRows2: this._getSelectedRows(selected, this._isSelectable)
});
},
textSelect: 'Select row',
textSelected: 'Selected',
textSelectAll: 'Select all rows',
textUnselect: 'Unselect row',
textUnselectAll: 'Unselect all rows'
}} />
</div>
</div>
);
}
}
Expandable rows allow for an additional table row for each item in the data
array that contains additional details. The additional row can be expanded or collapsed and can have its data displayed in any custom format. When using expandable rows, an additional column will be added to render the expand/collapse toggle button for rows and in the header for expanding/collapsing all rows. Use the expansion
property to enable expandable rows.
const userDataHIG = [
{uid: 1, jersey: 12, last: 'Brady', first: 'Tom', email: 'Tom.Brady@patriots.com', birthday: '1977-09-14', isAwesome: false},
{uid: 2, jersey: 3, last: 'Wilson', first: 'Russell', email: 'Russell.Wilson@seahawks.com', birthday: '1990-11-02', isAwesome: true},
{uid: 3, jersey: 9, last: 'Brees', first: 'Drew', email: 'Drew.Brees@saints.com', birthday: '1979-02-10', isAwesome: true},
{uid: 4, jersey: 2, last: 'Ryan', first: 'Matt', email: 'Matt.Ryan@falcons.com', birthday: '1988-03-25', isAwesome: true},
{uid: 5, jersey: 1, last: 'Newton', first: 'Cam', email: 'Cam.Newton@panthers.com', isAwesome: false}
];
class HIGDataGridEx08 extends React.Component {
constructor(props) {
super(props);
this.state = {
data: Sorters.numeric(userDataHIG, 'jersey', true),
expandedRows1: [],
expandedRows2: [1, 3]
};
}
_isExpandable = (row) => {
return row.uid % 2;
}
_getExpandedRows = (expanded, isExpandable) => {
let {
data
} = this.state;
let expandedRows = [];
if (expanded) {
data.forEach((row) => {
expandedRows = toggleRowState(expandedRows, row.uid, isExpandable(row));
});
}
return expandedRows;
}
_renderExpandedRow = (row) => {
return (
<span>
<strong>{row.first} {row.last}'s Bio:</strong><br />
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Phasellus in ligula at lacus venenatis rhoncus. Nam eget ultricies justo. Aliquam venenatis,
ipsum in lobortis ultricies, felis purus lobortis lacus, nec consequat dui tellus id enim.
</span>
);
}
render() {
return (
<Row>
<Col sm={6} xs={12}>
<DataGrid
caption={{
title: 'Expenses by vendor'
}}
columns={[
{propertyName: 'jersey', headerContent: 'Number'},
{propertyName: 'first', headerContent: 'First Name'},
{propertyName: 'last', headerContent: 'Last Name'}
]}
data={this.state.data}
empty={<DataGrid.Empty title='No users found' />}
expansion={{
isExpanded: (row, rowKey) => {
return this.state.expandedRows1.indexOf(rowKey) >= 0;
},
onExpandRow: (row, expanded, rowKey) => {
let {
expandedRows1
} = this.state;
this.setState({
expandedRows1: toggleRowState(expandedRows1, rowKey, expanded)
});
},
onExpandAll: (expanded) => {
this.setState({
expandedRows1: this._getExpandedRows(expanded, () => {
return true;
})
});
},
rowContent: this._renderExpandedRow,
textExpand: 'Expand row',
textExpandAll: 'Expand all rows',
textCollapse: 'Collapse row',
textCollapseAll: 'Collapse all rows'
}}
rowKey='uid' />
</Col>
<Col sm={6} xs={12}>
<DataGrid
caption={{
title: 'Player jersey numbers'
}}
columns={[
{propertyName: 'jersey', headerContent: 'Number'},
{propertyName: 'first', headerContent: 'First Name'},
{propertyName: 'last', headerContent: 'Last Name'}
]}
data={this.state.data}
empty={<DataGrid.Empty title='No users found' />}
expansion={{
isExpandable: this._isExpandable,
isExpanded: (row, rowKey) => {
return this.state.expandedRows2.indexOf(rowKey) >= 0;
},
onExpandRow: (row, expanded, rowKey) => {
let {
expandedRows2
} = this.state;
this.setState({
expandedRows2: toggleRowState(expandedRows2, rowKey, expanded)
});
},
onExpandAll: (expanded) => {
this.setState({
expandedRows2: this._getExpandedRows(expanded, this._isExpandable)
});
},
rowContent: this._renderExpandedRow,
textExpand: 'Expand row',
textExpandAll: 'Expand all rows',
textCollapse: 'Collapse row',
textCollapseAll: 'Collapse all rows'
}}
rowKey='uid' />
</Col>
</Row>
);
}
}
Summary rows are shown after the last row (e.g. totals or counts). Use the summaryRows
property to supply the custom content. This can be one row or multiple rows. For multiple rows, pass an array of nodes. The top-level element of each node passed MUST be a <tr>
. If the summary row is specific to totals, use the DataGrid.TotalsRow
component in place of a <tr>
to get the proper CSS class.
const userDataHIG = [
{uid: 1, jersey: 12, last: 'Brady', first: 'Tom', email: 'Tom.Brady@patriots.com', birthday: '1977-09-14', isAwesome: false},
{uid: 2, jersey: 3, last: 'Wilson', first: 'Russell', email: 'Russell.Wilson@seahawks.com', birthday: '1990-11-02', isAwesome: true},
{uid: 3, jersey: 9, last: 'Brees', first: 'Drew', email: 'Drew.Brees@saints.com', birthday: '1979-02-10', isAwesome: true},
{uid: 4, jersey: 2, last: 'Ryan', first: 'Matt', email: 'Matt.Ryan@falcons.com', birthday: '1988-03-25', isAwesome: true},
{uid: 5, jersey: 1, last: 'Newton', first: 'Cam', email: 'Cam.Newton@panthers.com', isAwesome: false}
];
class HIGDataGridEx06 extends React.Component {
constructor(props) {
super(props);
this.state = {
data: userDataHIG
};
}
_renderUserTotals() {
return (
<DataGrid.TotalsRow>
<td colSpan={3}>
Number of people
</td>
<td className='text-right'>
{this.state.data.length}
</td>
</DataGrid.TotalsRow>
);
}
render() {
return (
<div>
<DataGrid
caption={{
title: 'Player jersey numbers'
}}
columns={[
{propertyName: 'jersey', headerContent: 'Number'},
{propertyName: 'first', headerContent: 'First Name'},
{propertyName: 'last', headerContent: 'Last Name'},
{
propertyName: 'birthday',
headerContent: 'Birthday',
emptyCellLabel: 'Birthday not provided',
align: 'right'
}
]}
data={this.state.data}
empty={<DataGrid.Empty title='No users found' />}
open
summaryRows={this._renderUserTotals()} />
</div>
);
}
}
Summary group rows are shown after the last row of a group of data (e.g. subtotals or counts). Use the summaryGroupRowContent
property to supply a callback function that returns the custom content. This can be one row or multiple rows. For multiple rows, pass an array of nodes. The top-level element of each node passed MUST be a <tr>
. If the summary row is specific to totals, use the DataGrid.TotalsRow
component in place of a <tr>
to get the proper CSS class.
The grid utilizes a multi-dimensional array structure for showing groups of rows and then triggering the callback function to display the summary group row(s). Each index for the first dimension in the data
array represents a group of data rows. Each index for the second dimension represents a single row of data. The consumer can either construct their own multi-dimensional array or use the grouper
function (from NUI Widgets) to transform a single-dimension array into a multi-dimensional array.
NOTE: Since the consumer owns the data displayed in the grid, the consumer MUST use Override Sorting
(if any columns are marked sortable). The data will likely need to be sorted as a single-dimension array and then converted back to a multi-dimensional array for the grid to use.
const expenseData = [
{id: '1', date: '11/15/2017', vendor: 'Delta Airlines', category: 'Air', amount: 500.00, currencyCode: 'USD'},
{id: '5', date: '11/17/2017', vendor: 'Ruth Criss Steakhouse', category: 'Meals', amount: 125.00, currencyCode: 'USD'},
{id: '7', date: '11/16/2017', vendor: 'Hyatt', category: 'Lodging', amount: 265.00, currencyCode: 'USD'},
{id: '2', date: '11/15/2017', vendor: 'Airport Cafe', category: 'Meals', amount: 20.00, currencyCode: 'USD'},
{id: '3', date: '11/16/2017', vendor: 'Red Robin', category: 'Meals', amount: 30.95, currencyCode: 'USD'},
{id: '4', date: '11/16/2017', vendor: 'McDonald\'s', category: 'Meals', amount: 8.00, currencyCode: 'USD'},
{id: '6', date: '11/15/2017', vendor: 'Marriot', category: 'Lodging', amount: 295.00, currencyCode: 'USD'}
];
class HIGDataGridEx09 extends React.Component {
constructor(props) {
super(props);
this.state = {
data: grouper(expenseData, ['category'])
};
}
_renderAmount = (data) => {
return formatCurrency(data.amount);
}
_renderSubTotals = (groupData) => {
const subtotal = groupData.reduce((total, row) => {
return total + row.amount;
}, 0);
return (
<DataGrid.TotalsRow key='summary1'>
<td className='text-right' colSpan={4}>
Subtotal:
{formatCurrency(subtotal)}
</td>
</DataGrid.TotalsRow>
);
}
_renderTotals() {
const data = this.state.data || [];
const total = data.reduce((sum1, groupData) => {
return groupData.reduce((sum2, row) => {
return sum2 + row.amount;
}, sum1);
}, 0);
return (
<DataGrid.TotalsRow>
<td className='text-right' colSpan={4}>
Total:
{formatCurrency(total)}
</td>
</DataGrid.TotalsRow>
);
}
render() {
return (
<div>
<DataGrid
caption={{
title: 'Expenses by vendor'
}}
columns={[
{propertyName: 'id', headerContent: 'ID'},
{propertyName: 'date', headerContent: 'Date'},
{propertyName: 'vendor', headerContent: 'Vendor'},
{propertyName: 'amount', headerContent: 'Amount', bodyContent: this._renderAmount, align: 'right'}
]}
data={this.state.data}
empty={<DataGrid.Empty title='No users found' />}
open
summaryGroupRowContent={this._renderSubTotals}
summaryRows={this._renderTotals()} />
</div>
);
}
}
A method of viewing a subset of data within the table. Use Pager
or Pagination
to control which rows are currently visible. The consumer owns the paging component and will just pass new data
when a page changes.
Show a “loading” component instead of the table. Use the loading
property to define the “loading” component.
<DataGrid
caption={{
title: 'Test grid'
}}
columns={[
{propertyName: 'col1', headerContent: 'Column 1'},
{propertyName: 'col2', headerContent: 'Column 2'}
]}
empty={<DataGrid.Empty title='None found' />}
loading={{
show: true,
message: 'Please wait...'
}} />
When the data
property is missing or has zero items in the array, show an “empty” component instead of the table. Use the empty
property to define the “empty” component.
<DataGrid
caption={{
title: 'Empty grid'
}}
columns={[
{propertyName: 'col1', headerContent: 'Column 1'},
{propertyName: 'col2', headerContent: 'Column 2'}
]}
empty={<DataGrid.Empty title='None found' />} />
<DataGrid
caption={{
title: 'Empty grid'
}}
columns={[
{propertyName: 'col1', headerContent: 'Column 1'},
{propertyName: 'col2', headerContent: 'Column 2'}
]}
empty={<DataGrid.Empty
description='Additional description text'
title='None found' />} />
<DataGrid
caption={{
title: 'Empty grid'
}}
columns={[
{propertyName: 'col1', headerContent: 'Column 1'},
{propertyName: 'col2', headerContent: 'Column 2'}
]}
empty={<DataGrid.Empty
description='Additional description text'
image={<i className='icon-no text-danger' style={{fontSize: '60px'}} />}
title='None found' />} />
Adding the appropriate DataGrid.StickyHeader
component around the outside of a DataGrid
will allow the content of the table to scroll while leaving the header and footer frozen in place. In order to use this component this simply provide a bodyHeight
prop to the DataGrid.StickyHeader
component to set the desired height.
<DataGrid.StickyHeader
bodyHeight={'250px'}>
<DataGrid
caption={{
title: 'Player jersey numbers'
}}
columns={[
{propertyName: 'jersey', headerContent: 'Number'},
{propertyName: 'first', headerContent: 'First Name'},
{propertyName: 'last', headerContent: 'Last Name'},
{propertyName: 'birthday', headerContent: 'Birthday'}
]}
data={this.state.data}
empty={<DataGrid.Empty title='No users found' />}
open
summaryRows={this._renderUserTotals()} />
</DataGrid.StickyHeader>
Property | Type | Default | Description |
---|---|---|---|
caption | Object | Required | Defines the caption for the table. See caption for details about the available properties test. |
columns | Array of Objects | Required | Defines the properties for each of the columns in the table. See columns for details about the available properties for each column. |
empty | Node | Required | Defines the component for the “empty” state (no records found) when data is missing or empty. You can use the DataGrid.Empty component as a convenience. |
className | String | Custom classes to add to the <table> tag. | |
data | Array | The raw data. Each element in the array (in JSON format) represents a row in the table. If using summary group rows, the array needs to be multi-dimensional. See Summary Group Rows for a detailed explanation. | |
expansion | Object | Enables expandable rows. A new column will be added to the table to show the expand/collapse toggle button on expandable rows. See expansion for details about the available properties. In order for expandable rows to work correctly, rowKey needs to be supplied. | |
loading | Object | Defines the properties for the loading (spinner) component. See loading for details about the available properties. | |
open | Boolean | false | If true , the table’s bottom border will be removed. Use this property when the table’s container already has a border. |
rowKey | String or Function | Used to identify the unique key for a row of data. If a string is used, it identifies the field in the data to use as the key value for the row. If a function is used, it must return the key value for the row. The function will be passed the row of data (in JSON format). | |
selection | Object | Enables selectable rows. A new column will be added to the table to show the selection checkbox on selectable rows. See selection for details about the available properties. In order for selectable rows to work correctly, rowKey needs to be supplied. | |
size | String | 'md' | Grid size. Options are 'lg' , 'md' , 'sm' . |
sorting | Object | Enables sorting. See sorting for details about the available properties. | |
striped | Boolean | true | If true , rows will alternate background shades. |
summaryRows | Node | Defines the content of the summary row(s) at the bottom of the table. The top-level element of each node passed MUST be a <tr> . | |
tableBodyProps | Object | Custom attributes to apply to the <tbody> element. | |
tableBodyRowProps | Object or Function | Custom attributes to apply to a <tr> element in the <tbody> . If using a function, it will be passed the row of data, an isSelected flag and the rowKey value. | |
tableFooterProps | Object | Custom attributes to apply to the <tfoot> element. | |
tableFooterRowProps | Object | Custom attributes to apply to a <tr> element in the <tfoot> . | |
tableHeaderProps | Object | Custom attributes to apply to the <thead> element. | |
tableHeaderRowProps | Object | Custom attributes to apply to the <tr> element in the <thead> . |
Property | Parameters | Description |
---|---|---|
summaryGroupRowContent | groupData (Array of JSON data objects) | The content to display as the summary group table row(s). The top-level element of each node passed MUST be a <tr> . |
onChange | Callback function that executes upon a rerender of data grid. | |
onLoad | Callback function that executes upon a initial render of data grid. |
Either title
or summary
MUST be set to valid localized string. You may also set both values.
Property | Type | Default | Description |
---|---|---|---|
title | String | Localized assistive text for the title of the table. | |
summary | String | Localized assistive text with verbose description of the structure and content of a complex table or instructions on use. |
Property | Type | Default | Description |
---|---|---|---|
align | String | 'left' | The alignment for this column on each row and in the header. Options are 'left' , 'center' , 'right' . |
bodyProps | Object or Function | Custom attributes to apply to a <td> element. If using a function, it will be passed the row of data, an isSelected flag and the rowKey value. | |
emptyCellLabel | String | This will not be visible in the grid. This represents an accessible label for empty column values to be announced to assistive technology users navigating the grid. | |
headerContent | Node | The content to display in the column header cell in the <thead> . The content will be wrapped in a <th> element. | |
headerProps | Object | Custom attributes to apply to the <th> element. | |
isSortable | Boolean | false | Enables sorting for this column. The sorting property must also be supplied to support sorting. |
propertyName | String | Name of the data element in the data object. |
Property | Parameters | Description |
---|---|---|
bodyContent | row (JSON data object), isSelected (Boolean), rowKey (String), isExpanded (Boolean) | The content to display in a table cell in the <tbody> . It can return any renderable content and it will be wrapped in a <td> element. If omitted, the data for propertyName will be added as a string. |
sorter | data (Array of JSON data objects), propertyName (String), asc (Boolean) | Returns a copy of the data array sorted by the column identified by propertyName in the order specified by asc . When using built-in sorting, this property can be used to mark a column as sortable in place of isSortable . |
Property | Type | Default | Description |
---|---|---|---|
textCollapse | String | Required | Localized assistive text for an expanded row toggle button. |
textCollapseAll | String | Required | Localized assistive text for the “collapse all” toggle button. |
textExpand | String | Required | Localized assistive text for a collapsed row toggle button. |
textExpandAll | String | Required | Localized assistive text for the “expand all” toggle button. |
rowProps | Object or Function | Custom attributes to apply to a <tr> element for an expanded row in the <tbody> . If using a function, it will be passed the row of data, an isSelected flag and the rowKey value. |
Property | Parameters | Description |
---|---|---|
isExpanded | row (JSON data object), rowKey (String) | Required. Return true if the row should be expanded (additional table row shown). |
onExpandRow | row (JSON data object), expanded (Boolean), rowKey (String) | Required. Called when a row is toggled between expanded and collapsed. This is used to track state in the consuming component. |
rowContent | row (JSON data object), rowKey (String) | Required. The content to display in the expanded table row. It can return any renderable content and it will be wrapped in a <td> element. |
isExpandable | row (JSON data object) | Return true if the row can be expanded/collapsed. If not provided, it is assumed that all rows are expandable. |
onExpandAll | expanded (Boolean) | Called when the “expand/collapse all” toggle button in the header is clicked. This is used to track state in the consuming component. If not provided, no toggle button will be rendered in the header. |
Property | Type | Default | Description |
---|---|---|---|
message | String | Required | The message to show with the spinner. |
show | Boolean | When true , the “loading” <div> will show instead of the <table> . |
Property | Type | Default | Description |
---|---|---|---|
textSelect | String | Required | Localized assistive text for an unchecked row checkbox. |
textSelected | String | Required | Localized assistive text for a selected cell. |
textSelectAll | String | Required | Localized assistive text for the “select all” checkbox. |
textUnselect | String | Required | Localized assistive text for a checked row checkbox. |
textUnselectAll | String | Required | Localized assistive text for the “unselect all” checkbox. |
Property | Parameters | Description |
---|---|---|
isSelected | row (JSON data object), rowKey (String) | Required. Return true if the row should be selected (checked). |
onSelectRow | row (JSON data object), selected (Boolean), rowKey (String) | Required. Called when a row is toggled between selected (checked) and unselected (unchecked). This is used to track state in the consuming component. |
isSelectable | row (JSON data object) | Return true if the row can be selected (checked). If not provided, it is assumed that all rows are selectable. |
onSelectAll | selected (Boolean) | Called when the “select all” checkbox in the header is toggled between selected (checked) and unselected (unchecked). This is used to track state in the consuming component. If not provided, no checkbox will be rendered in the header. |
Property | Type | Default | Description |
---|---|---|---|
asc | Boolean | Required | Use true to sort in ascending order. |
propertyName | String | Required | The column identifier for the currently sorted column. |
Property | Parameters | Description |
---|---|---|
onSort | propertyName (String), event | Allows consumer to manage all sorting. Takes precedence over any column sorter properties. Called when the user clicks on a column header to change the sort field or sort direction. After the consumer sorts and passes the data , the sorting needs to be updated. If this property is not set, DataGrid will handle sorting. |
Property | Type | Default | Description |
---|---|---|---|
title | Node | Required | The “no records found” text to be shown when no data exists. |
description | Node | Additional descriptive text to show below the title . | |
image | Node | Image to show above the title . |
Property | Type | Default | Description |
---|---|---|---|
children | Node | Required | Content for the table row. |
className | String | Custom classes to add to the <tr> tag. |
Property | Type | Default | Description |
---|---|---|---|
bodyHeight | String | Required | Sets the height of the DataGrid ’s body content to provide a vertical scrolling effect. Must provide both the value and unit of measurement. |
import grouper from '@concur/nui-widgets/lib/utils/grouper';
Assign objects into groups by one or more properties, by object value, or by using a comparator function. See grouper API for usage details.