Skip to content

Commit d77f4d8

Browse files
committed
feat(table): allow table actions
1 parent c0be209 commit d77f4d8

File tree

5 files changed

+104
-11
lines changed

5 files changed

+104
-11
lines changed

README.md

+6-1
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@ A React implementation of Boostrap v4 components.
66

77
## Roadmap
88

9-
- [] Table
109
- [] Dialogs
1110
- [] Tabs
1211
- [] Pagination
12+
- [] Smartable
1313
- [] Form validations (dependent field validation)
1414
- [] Form Autocomplete
1515
- [] Form Range
@@ -35,3 +35,8 @@ A React implementation of Boostrap v4 components.
3535
- [] Progress bar
3636
- [] Tooltip
3737
- [] Popovers
38+
- [] Table with row details
39+
- [] Table footer (sums, counters, etc)
40+
- [] Table with sticky footer
41+
- [] Table with sticky columns
42+
- [] Table with sticky header

demo/demo.jsx

+43-2
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ function TableExamples() {
147147
]}
148148
/>
149149
</div>
150+
150151
<div className="col">
151152
<h2>Table with formated colums</h2>
152153
<Table
@@ -162,10 +163,18 @@ function TableExamples() {
162163
]}
163164
/>
164165
</div>
166+
165167
<div className="col">
166168
<h2>Table with formatted values </h2>
167169
<Table
168170
columns={[
171+
{
172+
attribute: 'selected',
173+
label: '#',
174+
format() {
175+
return <input type="checkbox" />;
176+
},
177+
},
169178
{
170179
attribute: 'a',
171180
label: 'A',
@@ -183,8 +192,8 @@ function TableExamples() {
183192
{
184193
attribute: 'c',
185194
label: 'C',
186-
format(v, doc) {
187-
return v + doc.c;
195+
format(_, __, docIndex) {
196+
return <strong>{docIndex + 1}</strong>;
188197
},
189198
},
190199
]}
@@ -215,6 +224,38 @@ function TableExamples() {
215224
rowClass={(doc) => (doc.b % 2 === 1 ? 'table-primary' : '')}
216225
/>
217226
</div>
227+
228+
<div className="col">
229+
<h2>Table with row actions</h2>
230+
<Table
231+
columns={[
232+
{ attribute: 'a', label: 'A', align: 'center' },
233+
{ attribute: 'b', label: 'B', align: 'right' },
234+
{ attribute: 'c', label: 'C' },
235+
]}
236+
docs={[
237+
{ a: 1, b: 2, c: 3 },
238+
{ a: 4, b: 5, c: 6 },
239+
{ a: 7, b: 8, c: 9 },
240+
]}
241+
actions={[
242+
{
243+
title: 'View details',
244+
content: <span>V</span>,
245+
link(doc) {
246+
return `#/${doc.a}`;
247+
},
248+
},
249+
{
250+
title: 'Remove item',
251+
content: '-',
252+
onClick(doc) {
253+
console.log('removing', doc);
254+
},
255+
},
256+
]}
257+
/>
258+
</div>
218259
</div>
219260
</div>
220261
);

src/table/Table.jsx

+17-3
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,19 @@ import { TableHead } from './TableHead';
33
import { TableBody } from './TableBody';
44
import { normalizeColumns } from './table-helpers';
55

6-
export function Table({ docs, columns, striped, bordered, hover, small, dark, rowClass, caption }) {
6+
export function Table({
7+
docs,
8+
columns,
9+
striped,
10+
bordered,
11+
hover,
12+
small,
13+
dark,
14+
rowClass,
15+
caption,
16+
actions,
17+
actionLabel,
18+
}) {
719
const normalizedColumns = normalizeColumns(columns);
820

921
const tableClasses = [
@@ -14,12 +26,13 @@ export function Table({ docs, columns, striped, bordered, hover, small, dark, ro
1426
small && 'table-sm',
1527
dark && 'table-dark',
1628
].join(' ');
29+
1730
return (
1831
<div className="table-responsive">
1932
<table className={tableClasses}>
2033
{caption && <caption>{caption}</caption>}
21-
<TableHead columns={normalizedColumns} />
22-
<TableBody docs={docs} columns={normalizedColumns} rowClass={rowClass} />
34+
<TableHead {...{ actions, actionLabel }} columns={normalizedColumns} />
35+
<TableBody {...{ docs, rowClass, actions }} columns={normalizedColumns} />
2336
</table>
2437
</div>
2538
);
@@ -31,5 +44,6 @@ Table.defaultProps = {
3144
hover: true,
3245
small: true,
3346
dark: false,
47+
actionLabel: 'Actions',
3448
rowClass: () => '',
3549
};

src/table/TableBody.jsx

+36-4
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,60 @@
11
import React from 'react';
22
import { getColumnClass } from './table-helpers';
33

4-
export function TableBody({ columns, docs, rowClass }) {
4+
export function TableBody({ columns, docs, rowClass, actions }) {
55
return (
66
<tbody>
77
{docs.map((doc, docIndex) => (
88
<tr key={docIndex} className={rowClass(doc)}>
99
{columns.map((column, columnIndex) => (
1010
<td key={columnIndex} className={getColumnClass(column)}>
11-
{getColumnValue(doc, column)}
11+
{getColumnValue(doc, column, docIndex)}
1212
</td>
1313
))}
14+
15+
{actions && (
16+
<td className="text-center">
17+
{actions.map((action, actionIndex) => (
18+
<a
19+
key={actionIndex}
20+
title={action.title}
21+
{...getActionProps(action, doc)}
22+
className={actionIndex > 0 ? 'ml-2' : ''}
23+
>
24+
{action.content}
25+
</a>
26+
))}
27+
</td>
28+
)}
1429
</tr>
1530
))}
1631
</tbody>
1732
);
1833
}
1934

20-
function getColumnValue(doc, column) {
35+
function getColumnValue(doc, column, docIndex) {
2136
let rawValue = doc[column.attribute];
2237

2338
if (!column.format) {
2439
return rawValue;
2540
}
2641

27-
return column.format(rawValue, doc);
42+
return column.format(rawValue, doc, docIndex);
43+
}
44+
45+
function getActionProps(action, doc) {
46+
const props = {};
47+
48+
if (action.onClick) {
49+
props.href = '';
50+
props.onClick = (e) => {
51+
e.stopPropagation();
52+
e.preventDefault();
53+
action.onClick(doc);
54+
};
55+
} else if (action.link) {
56+
props.href = action.link(doc);
57+
}
58+
59+
return props;
2860
}

src/table/TableHead.jsx

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React from 'react';
22
import { getColumnClass } from './table-helpers';
33

4-
export function TableHead({ columns }) {
4+
export function TableHead({ columns, actions, actionLabel }) {
55
return (
66
<thead>
77
<tr>
@@ -10,6 +10,7 @@ export function TableHead({ columns }) {
1010
{column.label}
1111
</th>
1212
))}
13+
{actions && <th className="text-center">{actionLabel}</th>}
1314
</tr>
1415
</thead>
1516
);

0 commit comments

Comments
 (0)