@eisgs/table
v3.2.0
Published
`columns` в качестве опций принимает массив с ключами `id`,`title`,`renderInfo`,`render`,`sort`,`styles`
Downloads
65
Readme
Компонент Table
columns
в качестве опций принимает массив с ключами id
,title
,renderInfo
,render
,sort
,styles
variant
переключает внешний вид шапки
cellAlign
выравнивает контент в ячейках, subColumns
наследуют переданное значение
sort
и onSort
управляют сортировкой. sort
объект с ключами key
и direction
import { Typography } from '@eisgs/typography';
import { Radio } from '@eisgs/radio';
import { Checkbox } from '@eisgs/checkbox';
const columns = [
{
id: 1,
title: 'Адрес объекта',
size: 2,
renderInfo: 'Подсказка к колонке',
render: ({ address }) => (
<Typography type="p2" weight="bold">
{address}
</Typography>
),
sort: {
key: 'address',
},
},
{
id: 2,
title: 'Застройщик банкрот',
size: 2,
render: ({ developer }) => (
<Typography type="p2">
{developer}
</Typography>
),
sort: {
key: 'developer',
},
},
{
id: 3,
title: 'Решение наб.совета Фонда',
render: ({ decision }) => (
<Typography type="p2">
{decision}
</Typography>
),
sort: {
key: 'decision',
},
},
{
id: 4,
title: 'Определение арбитражного суда',
render: ({ definition }) => (
<Typography type="p2">
{definition}
</Typography>
),
sort: {
key: 'definition',
},
},
{
id: 5,
title: 'Статус объекта',
render: ({ status }) => (
<Typography type="p2">
{status}
</Typography>
),
sort: {
key: 'status',
direction: 'DESC',
},
},
];
const data = [
{
address: 'город Москва, Ленинградский проспект, д. 14',
developer: 'ООО Одуванчик',
decision: 'Нет',
definition: 'Нет',
status: 0,
},
{
address: 'город Магадан, район Центральный, улица Строителей, д. 77',
developer: 'ООО ЛенИнвестСтрой',
decision: 'Есть',
definition: 'Есть',
status: 6,
},
{
address: 'город Москва, Ленинградский проспект, д. 14',
developer: 'ООО Одуванчик',
decision: 'Есть',
definition: 'Есть',
status: 29,
},
{
address: 'город Екатеринбург, район Верх-Исетский, улица Суходольская, д. 2',
developer: 'ООО Успех',
decision: 'Нет',
definition: 'Есть',
status: 3,
},
{
address: 'город Магадан, район Центральный, улица Строителей, д. 77',
developer: 'ООО ЛенИнвестСтрой',
decision: 'Есть',
definition: 'Нет',
status: 1,
},
{
address: 'город Магадан, район Центральный, улица Строителей, д. 77',
developer: 'ООО ЛенИнвестСтрой',
decision: 'Нет',
definition: 'Есть',
status: 25,
},
];
const ColumnKeys = ['address', 'developer', 'decision', 'definition', 'status'];
const variantOptions = ['base', 'inner', 'sidebar'].map((variant) => ({ id: variant, description: variant, code: variant }));
const [tableData, setTableData] = React.useState(data);
const [sort, setSort] = React.useState(undefined);
const [variant, setVariant] = React.useState(variantOptions[0].code);
const [cellAlign, setCellAlign] = React.useState(false);
const handleSort = (argSort) => {
setSort(argSort);
if (argSort && !argSort.key) {
return;
}
if (ColumnKeys.includes(argSort.key)) {
const sorted = [...tableData].sort((a, b) => {
if (argSort.direction === 'ASC') {
return a[argSort.key] > b[argSort.key] ? 1 : -1;
}
return a[argSort.key] > b[argSort.key] ? -1 : 1;
});
setTableData(sorted);
}
};
<>
<Typography type="p1" weight="bold" style={{ margin: '20px 0' }}>
Variant:
</Typography>
<Radio options={variantOptions} onChange={setVariant} value={variant} />
<Typography type="p1" weight="bold" style={{ margin: '20px 0' }}>
Cell align:
</Typography>
<Checkbox onChange={setCellAlign} checked={cellAlign}>
Top
</Checkbox>
<Table
{...cellAlign && {cellAlign: 'top'}}
variant={variant}
columns={columns}
data={tableData}
sort={sort}
onSort={handleSort}
/>
</>;
Вложенные таблицы
Для отображения вложенных элементов необходимо передать конфиг subColumns
, по аналогии с columns
.
Чтобы по нажатию на <Row>
отображались подтаблицы, необходимо передать флаг withSubRowCollapseOnClick
.
Ожидается, что в <Table>
будет передан параметр subColumnsDataKey
, который представляет собой ключ в массив данных, содержимое которого будет
использовано при рендере подтаблиц.
Для кастомной логики есть возможность передать кастомный компонент SubRowComponent
.
В массиве с данными в data
крайне желательно иметь стабильные ID у элементов. В противном случае, при, например, сортировке данных,
т.е. при измении data
, информация о открытых/закрытых подтаблиц будет потеряна.
import { Typography } from '@eisgs/typography';
import { Radio } from '@eisgs/radio';
import { Checkbox } from '@eisgs/checkbox';
const columns = [
{
id: 1,
title: 'Адрес объекта',
size: 2,
renderInfo: 'Подсказка к колонке',
render: ({ address }) => (
<Typography type="p2" weight="bold">
{address}
</Typography>
),
sort: {
key: 'address',
},
},
{
id: 2,
title: 'Застройщик банкрот',
size: 2,
render: ({ developer }) => (
<Typography type="p2">
{developer}
</Typography>
),
sort: {
key: 'developer',
},
},
{
id: 3,
title: 'Решение наб.совета Фонда',
render: ({ decision }) => (
<Typography type="p2">
{decision}
</Typography>
),
sort: {
key: 'decision',
},
},
{
id: 4,
title: 'Определение арбитражного суда',
render: ({ definition }) => (
<Typography type="p2">
{definition}
</Typography>
),
sort: {
key: 'definition',
},
},
{
id: 5,
title: 'Статус объекта',
render: ({ status }) => (
<Typography type="p2">
{status}
</Typography>
),
sort: {
key: 'status',
direction: 'DESC',
},
},
];
const subColumns = [
{
id: 1,
title: 'Sub table',
size: 2,
renderInfo: 'Подсказка к колонке',
render: ({ address }) => (
<Typography type="p2">
{address}
</Typography>
),
},
{
id: 2,
title: 'Sub table',
size: 2,
renderInfo: 'Подсказка к колонке',
render: ({ developer }) => (
<Typography type="p2">
{developer}
</Typography>
),
},
{
id: 3,
title: 'Sub table',
renderInfo: 'Подсказка к колонке',
render: ({ decision }) => (
<Typography type="p2">
{decision}
</Typography>
),
},
{
id: 4,
title: 'Sub table',
renderInfo: 'Подсказка к колонке',
render: ({ definition }) => (
<Typography type="p2">
{definition}
</Typography>
),
},
{
id: 5,
title: 'Sub table',
renderInfo: 'Подсказка к колонке',
render: ({ status }) => (
<Typography type="p2">
{status}
</Typography>
),
},
]
const data = [
{
id: 'id1',
address: 'город Москва, Ленинградский проспект, д. 14',
developer: 'ООО Одуванчик',
decision: 'Нет',
definition: 'Нет',
status: 0,
history: [
{
id: 1,
address: 'город Москва, Ленинградский проспект, д. 14 город Москва, Ленинградский проспект, д. 14',
developer: 'ООО Одуванчик',
decision: 'Нет',
definition: 'Нет',
status: 0,
},
{
id: 2,
address: 'город Москва, Ленинградский проспект, д. 14',
developer: 'ООО Одуванчик',
decision: 'Нет',
definition: 'Нет',
status: 0,
},
],
},
{
id: 'id2',
address: 'город Москва, Неленинградский проспект, д. 14',
developer: 'ООО Одуванчик',
decision: 'Нет',
definition: 'Нет',
status: 0,
history: [
{
id: 1,
address: 'город Москва, Ленинградский проспект, д. 14',
developer: 'ООО Одуванчик',
decision: 'Нет',
definition: 'Нет',
status: 0,
},
{
id: 2,
address: 'город Москва, Ленинградский проспект, д. 14',
developer: 'ООО Одуванчик',
decision: 'Нет',
definition: 'Нет',
status: 0,
},
],
},
];
const ColumnKeys = ['address', 'developer', 'decision', 'definition', 'status'];
const variantOptions = ['base', 'inner', 'sidebar'].map((variant) => ({ id: variant, description: variant, code: variant }));
const [tableData, setTableData] = React.useState(data);
const [sort, setSort] = React.useState(undefined);
const [variant, setVariant] = React.useState(variantOptions[0].code);
const [cellAlign, setCellAlign] = React.useState(false);
const handleSort = (argSort) => {
setSort(argSort);
if (argSort && !argSort.key) {
return;
}
if (ColumnKeys.includes(argSort.key)) {
const sorted = [...tableData].sort((a, b) => {
if (argSort.direction === 'ASC') {
return a[argSort.key] > b[argSort.key] ? 1 : -1;
}
return a[argSort.key] > b[argSort.key] ? -1 : 1;
});
setTableData(sorted);
}
};
const SubRowComponent = ({ row }) => {
return <code>{JSON.stringify(row)}</code>;
}
<>
<Typography type="p1" weight="bold" style={{ margin: '20px 0' }}>
Variant:
</Typography>
<Radio options={variantOptions} onChange={setVariant} value={variant} />
<Typography type="p1" weight="bold" style={{ margin: '20px 0' }}>
Cell align:
</Typography>
<Checkbox onChange={setCellAlign} checked={cellAlign}>
Top
</Checkbox>
<Table
{...cellAlign && {cellAlign: 'top'}}
withSubRowCollapseOnClick
variant={variant}
columns={columns}
subColumns={subColumns}
data={tableData}
subColumnsDataKey="history"
onSubRowClick={() => { alert('Обработчик нажатия на subRow'); }}
sort={sort}
onSort={handleSort}
/>
<Typography type="p1" style={{ margin: '20px 0' }}>
Кастомный SubRowComponent
</Typography>
<Table
{...cellAlign && {cellAlign: 'top'}}
withSubRowCollapseOnClick
variant={variant}
columns={columns}
subColumns={subColumns}
data={tableData}
subColumnsDataKey="history"
onSubRowClick={() => { alert('Обработчик нажатия на subRow'); }}
sort={sort}
onSort={handleSort}
SubRowComponent={<SubRowComponent />}
/>
</>
Пагинация
В компонент можно передать конфиг для пагинации pagination
(принимает все обязательные параметры компонента Pagination
),
по умолчанию пагинация отключена
import { Typography } from '@eisgs/typography';
const columns = [
{
id: 1,
title: 'Адрес объекта',
size: 2,
renderInfo: 'Подсказка к колонке',
render: ({ address }) => (
<Typography type="p2" weight="bold">
{address}
</Typography>
),
sort: {
key: 'address',
},
},
{
id: 2,
title: 'Застройщик банкрот',
size: 2,
render: ({ developer }) => (
<Typography type="p2">
{developer}
</Typography>
),
sort: {
key: 'developer',
},
},
{
id: 3,
title: 'Решение наб.совета Фонда',
render: ({ decision }) => (
<Typography type="p2">
{decision}
</Typography>
),
sort: {
key: 'decision',
},
},
{
id: 4,
title: 'Определение арбитражного суда',
render: ({ definition }) => (
<Typography type="p2">
{definition}
</Typography>
),
sort: {
key: 'definition',
},
},
{
id: 5,
title: 'Статус объекта',
render: ({ status }) => (
<Typography type="p2">
{status}
</Typography>
),
sort: {
key: 'status',
direction: 'DESC',
},
},
];
function getRandom(min, max) {
return min + Math.random() * (max - min);
}
const data = Array.from(Array(100)).map((_, index) => {
const realIndex = index + 1;
const random = getRandom(0, 1);
return {
address: `Адрес ${realIndex}`,
developer: `${random > .5 ? 'ООО' : 'ЗАО'} Застройщик ${realIndex}`,
decision: random > .5 ? 'Есть' : 'Нет',
definition: random > .5 ? 'Есть' : 'Нет',
status: realIndex,
}
})
const ColumnKeys = ['address', 'developer', 'decision', 'definition', 'status'];
const limits = [10, 20, 50];
const [tableData, setTableData] = React.useState(data);
const [sort, setSort] = React.useState(undefined);
const [page, setPage] = React.useState(1);
const [limit, setLimit] = React.useState(limits[0]);
const dataByParams = tableData.slice((page - 1) * limit, page * limit);
const total = tableData.length;
const handleSort = (argSort) => {
setSort(argSort);
if (argSort && !argSort.key) {
return;
}
if (ColumnKeys.includes(argSort.key)) {
const sorted = [...tableData].sort((a, b) => {
if (argSort.direction === 'ASC') {
return a[argSort.key] > b[argSort.key] ? 1 : -1;
}
return a[argSort.key] > b[argSort.key] ? -1 : 1;
});
setTableData(sorted);
}
};
const pagination = React.useMemo(() => ({
limit,
limits,
page,
total,
onLimitChange: setLimit,
onPageChange: setPage,
}), [limits, limit, page, total]);
<Table
variant="base"
columns={columns}
data={tableData.slice((page - 1) * limit, page * limit)}
sort={sort}
onSort={handleSort}
pagination={{
limit,
limits,
page,
total: tableData.length,
onLimitChange: setLimit,
onPageChange: setPage,
}}
/>