Skip to content

Commit

Permalink
Add support for expandable rows to EuiBasicTable. (#585)
Browse files Browse the repository at this point in the history
* Add support for expandable rows to EuiBasicTable.
  • Loading branch information
cjcenizal authored Mar 28, 2018
1 parent e33f734 commit f6836c4
Show file tree
Hide file tree
Showing 9 changed files with 1,411 additions and 882 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# [`master`](https://github.com/elastic/eui/tree/master)

- Relaxed query syntax of `EuiSearchBar` to allow usage of hyphens without escaping ([#581](https://github.com/elastic/eui/pull/581))
- Add support for expandable rows to `EuiBasicTable` ([#585](https://github.com/elastic/eui/pull/585))

# [`0.0.35`](https://github.com/elastic/eui/tree/v0.0.35)

Expand Down
205 changes: 205 additions & 0 deletions src-docs/src/views/tables/expanding_rows/expanding_rows.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
import React, {
Component,
Fragment,
} from 'react';
import { formatDate } from '../../../../../src/services/format';
import { createDataStore } from '../data_store';

import {
EuiBasicTable,
EuiLink,
EuiHealth,
EuiButton,
EuiDescriptionList,
} from '../../../../../src/components';

/*
Example user object:
{
id: '1',
firstName: 'john',
lastName: 'doe',
github: 'johndoe',
dateOfBirth: Date.now(),
nationality: 'NL',
online: true
}
Example country object:
{
code: 'NL',
name: 'Netherlands',
flag: '🇳🇱'
}
*/

const store = createDataStore();

export class Table extends Component {
constructor(props) {
super(props);

this.state = {
pageIndex: 0,
pageSize: 5,
sortField: 'firstName',
sortDirection: 'asc',
selectedItems: [],
itemIdToExpandedRowMap: {},
};
}

onTableChange = ({ page = {}, sort = {} }) => {
const {
index: pageIndex,
size: pageSize,
} = page;

const {
field: sortField,
direction: sortDirection,
} = sort;

this.setState({
pageIndex,
pageSize,
sortField,
sortDirection,
});
};

onSelectionChange = (selectedItems) => {
this.setState({ selectedItems });
};

onClickDelete = () => {
const { selectedItems } = this.state;
store.deleteUsers(...selectedItems.map(user => user.id));

this.setState({
selectedItems: []
});
};

renderDeleteButton() {
const { selectedItems } = this.state;

if (selectedItems.length === 0) {
return;
}

return (
<EuiButton
color="danger"
iconType="trash"
onClick={this.onClickDelete}
>
Delete {selectedItems.length} Users
</EuiButton>
);
}

toggleDetails = (item) => {
const itemIdToExpandedRowMap = { ...this.state.itemIdToExpandedRowMap };
if (itemIdToExpandedRowMap[item.id]) {
delete itemIdToExpandedRowMap[item.id];
} else {
const { nationality, online } = item;
const country = store.getCountry(nationality);
const color = online ? 'success' : 'danger';
const label = online ? 'Online' : 'Offline';
const listItems = [
{
title: 'Nationality',
description: `${country.flag} ${country.name}`,
}, {
title: 'Online',
description: <EuiHealth color={color}>{label}</EuiHealth>,
}
];
itemIdToExpandedRowMap[item.id] = (
<EuiDescriptionList listItems={listItems} />
);
}
this.setState({ itemIdToExpandedRowMap });
};

render() {
const {
pageIndex,
pageSize,
sortField,
sortDirection,
itemIdToExpandedRowMap,
} = this.state;

const {
pageOfItems,
totalItemCount,
} = store.findUsers(pageIndex, pageSize, sortField, sortDirection);

const deleteButton = this.renderDeleteButton();

const columns = [{
field: 'firstName',
name: 'First Name',
sortable: true,
truncateText: true,
}, {
field: 'lastName',
name: 'Last Name',
truncateText: true,
}, {
field: 'dateOfBirth',
name: 'Date of Birth',
dataType: 'date',
render: (date) => formatDate(date, 'dobLong'),
sortable: true
}, {
name: 'Details',
render: (item) => (
<EuiLink onClick={() => this.toggleDetails(item)}>
{itemIdToExpandedRowMap[item.id] ? 'Hide' : 'Show'}
</EuiLink>
)
}];

const pagination = {
pageIndex: pageIndex,
pageSize: pageSize,
totalItemCount: totalItemCount,
pageSizeOptions: [3, 5, 8]
};

const sorting = {
sort: {
field: sortField,
direction: sortDirection,
},
};

const selection = {
itemId: 'id',
selectable: (user) => user.online,
selectableMessage: (selectable) => !selectable ? 'User is currently offline' : undefined,
onSelectionChange: this.onSelectionChange
};

return (
<Fragment>
{deleteButton}
<EuiBasicTable
items={pageOfItems}
itemIdToExpandedRowMap={this.state.itemIdToExpandedRowMap}
columns={columns}
pagination={pagination}
sorting={sorting}
selection={selection}
onChange={this.onTableChange}
/>
</Fragment>
);
}
}
32 changes: 32 additions & 0 deletions src-docs/src/views/tables/expanding_rows/expanding_rows_section.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import React from 'react';
import {
EuiBasicTable,
EuiCode
} from '../../../../../src/components';
import { GuideSectionTypes } from '../../../components';
import { renderToHtml } from '../../../services';

import { Table } from './expanding_rows';
const source = require('!!raw-loader!./expanding_rows');
const html = renderToHtml(Table);

export const section = {
title: 'Expanding rows',
source: [
{
type: GuideSectionTypes.JS,
code: source,
}, {
type: GuideSectionTypes.HTML,
code: html,
}
],
text: (
<p>
You can expand rows by passing in a <EuiCode>itemIdToExpandedRowMap</EuiCode> prop
which will contain the content you want rendered inside the expanded row.
</p>
),
components: { EuiBasicTable },
demo: <Table/>,
};
1 change: 1 addition & 0 deletions src-docs/src/views/tables/expanding_rows/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { section } from './expanding_rows_section';
2 changes: 2 additions & 0 deletions src-docs/src/views/tables/tables_example.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { section as basicSection } from './basic';
import { section as paginatedSection } from './paginated';
import { section as sortingSection } from './sorting';
import { section as selectionSection } from './selection';
import { section as expandingRowsSection } from './expanding_rows';
import { section as actionsSection } from './actions';
import {
section as inMemorySection,
Expand Down Expand Up @@ -46,6 +47,7 @@ export const TableExample = {
paginatedSection,
sortingSection,
selectionSection,
expandingRowsSection,
actionsSection,
inMemorySection,
inMemorySelectionSection,
Expand Down
Loading

0 comments on commit f6836c4

Please sign in to comment.