Table (Synthetic)
General
a) Basic
| # | Title 1 | Title 2 | Title 3 | Title 4 | Title 5 | Title 6 | Title 7 | Long Title 8 | Long Title 9 | Long Title 10 | Long Title 11 | Long Title 12 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | David | Jone | Good | Test 4 | Test 5 | Test 6 | Test 7 | Test 8 | Test 9 | Test 10 | Test 11 | Test 12 |
| 2 | Chuckie | Jone | BAD | Test 4 | Test 5 | Test 6 | Test 7 | Test 8 | Test 9 | Test 10 | Test 11 | Test 12 |
| 3 | Hi There | Cool | Test 4 | Test 5 | Test 6 | Test 7 | Test 8 | Test 9 | Test 10 | Test 11 | Test 12 | |
Show Code
import React from "react";
import {
Table,
TableBody,
TableCell,
TableHead,
TableRow,
} from 'funda-ui/Table';
// component styles
import 'funda-ui/Table/index.css';
export default () => {
return (
<>
<Table
tableClassName="table table-hover table-bordered table-striped align-middle"
>
<TableHead>
<TableRow>
<TableCell scope="col" nowrap>#</TableCell>
<TableCell scope="col" nowrap>Title 1</TableCell>
<TableCell scope="col" nowrap>Title 2</TableCell>
<TableCell scope="col" nowrap>Title 3</TableCell>
<TableCell scope="col" nowrap>Title 4</TableCell>
<TableCell scope="col" nowrap>Title 5</TableCell>
<TableCell scope="col" nowrap>Title 6</TableCell>
<TableCell scope="col" nowrap>Title 7</TableCell>
<TableCell scope="col" nowrap>Long Title 8</TableCell>
<TableCell scope="col" nowrap>Long Title 9</TableCell>
<TableCell scope="col" nowrap>Long Title 10</TableCell>
<TableCell scope="col" nowrap>Long Title 11</TableCell>
<TableCell scope="col" nowrap>Long Title 12</TableCell>
</TableRow>
</TableHead>
<TableBody>
<TableRow active>
<TableCell scope="row">1</TableCell>
<TableCell>David</TableCell>
<TableCell>Jone</TableCell>
<TableCell>Good</TableCell>
<TableCell>Test 4</TableCell>
<TableCell>Test 5</TableCell>
<TableCell>Test 6</TableCell>
<TableCell>Test 7</TableCell>
<TableCell>Test 8</TableCell>
<TableCell>Test 9</TableCell>
<TableCell>Test 10</TableCell>
<TableCell>Test 11</TableCell>
<TableCell>Test 12</TableCell>
</TableRow>
<TableRow>
<TableCell scope="row">2</TableCell>
<TableCell>Chuckie</TableCell>
<TableCell>Jone</TableCell>
<TableCell>BAD</TableCell>
<TableCell>Test 4</TableCell>
<TableCell>Test 5</TableCell>
<TableCell>Test 6</TableCell>
<TableCell>Test 7</TableCell>
<TableCell>Test 8</TableCell>
<TableCell>Test 9</TableCell>
<TableCell>Test 10</TableCell>
<TableCell>Test 11</TableCell>
<TableCell>Test 12</TableCell>
</TableRow>
<TableRow>
<TableCell scope="row">3</TableCell>
<TableCell colSpan={2}>
Hi There
</TableCell>
<TableCell>Cool</TableCell>
<TableCell>Test 4</TableCell>
<TableCell>Test 5</TableCell>
<TableCell>Test 6</TableCell>
<TableCell>Test 7</TableCell>
<TableCell>Test 8</TableCell>
<TableCell>Test 9</TableCell>
<TableCell>Test 10</TableCell>
<TableCell>Test 11</TableCell>
<TableCell>Test 12</TableCell>
</TableRow>
</TableBody>
</Table>
</>
);
}b) Cell Auto Width
| # | Title 1 | Title 2 | Title 3 |
|---|---|---|---|
| 1 | David | Jone | Good |
| 2 | Chuckie | Jone | Pictures are worth a thousand words, right? So Tom x 1,000. |
| 3 | Hi There | Cool | |
Show Code
import React from "react";
import {
Table,
TableBody,
TableCell,
TableHead,
TableRow,
} from 'funda-ui/Table';
// component styles
import 'funda-ui/Table/index.css';
export default () => {
return (
<>
<Table
cellAutoWidth
tableClassName="table table-hover table-bordered table-striped"
>
<TableHead className="table-light">
<TableRow>
<TableCell scope="col" nowrap>#</TableCell>
<TableCell scope="col" nowrap>Title 1</TableCell>
<TableCell scope="col" nowrap>Title 2</TableCell>
<TableCell scope="col" nowrap>Title 3</TableCell>
</TableRow>
</TableHead>
<TableBody>
<TableRow active>
<TableCell scope="row">1</TableCell>
<TableCell>David</TableCell>
<TableCell>Jone</TableCell>
<TableCell>Good</TableCell>
</TableRow>
<TableRow>
<TableCell scope="row">2</TableCell>
<TableCell>Chuckie</TableCell>
<TableCell>Jone</TableCell>
<TableCell>Pictures are worth a thousand words, right? So Tom x 1,000.</TableCell>
</TableRow>
<TableRow>
<TableCell scope="row">3</TableCell>
<TableCell colSpan={2}>
Hi There
</TableCell>
<TableCell>Cool</TableCell>
</TableRow>
</TableBody>
</Table>
</>
);
}c) Enhanced Responsive
Valid when the device width is less than or equal to 768px.
| # | Title 1 | Title 2 | Title 3 |
|---|---|---|---|
| 0 | David | Jone | GOOD |
| 1 | Chuckie | Jone | BAD |
| 2 | Smith Jone | Lomi | Pictures are worth a thousand words, right? So Tom x 1,000. |
| 3 | Frank | Alice | PERFECT |
Show Code
import React from "react";
import {
Table,
TableBody,
TableCell,
TableHead,
TableRow,
} from 'funda-ui/Table';
// component styles
import 'funda-ui/Table/index.css';
const tableData = [
{name: 'David', friend: 'Jone', condition: 'GOOD'},
{name: 'Chuckie', friend: 'Jone', condition: 'BAD'},
{name: 'Smith Jone', friend: 'Lomi', condition: 'Pictures are worth a thousand words, right? So Tom x 1,000.'},
{name: 'Frank', friend: 'Alice', condition: 'PERFECT'},
];
const responseTitle = (s: any) => {
return typeof s === 'string' ? s.replace(/(<([^>]+)>)/ig, '') : s;
};
export default () => {
return (
<>
<Table
enhancedResponsive
tableClassName="table table-bordered"
>
<TableHead>
<TableRow>
<TableCell scope="col" nowrap>#</TableCell>
<TableCell scope="col" nowrap>Title 1</TableCell>
<TableCell scope="col" nowrap>Title 2</TableCell>
<TableCell scope="col" nowrap>Title 3</TableCell>
</TableRow>
</TableHead>
<TableBody>
{tableData.map((item: any, index: number) => {
return <TableRow
key={`row-${index}`}
data-key={`row-${index}`}
itemData={item}
data-table-text={responseTitle(item.name)}
>
<TableCell scope="row" data-table-text="#">{index}</TableCell>
<TableCell data-table-text="Title 1">{item.name}</TableCell>
<TableCell data-table-text="Title 2">{item.friend}</TableCell>
<TableCell data-table-text="Title 3">{item.condition}</TableCell>
</TableRow>
})}
</TableBody>
</Table>
</>
);
}d) Enhanced Responsive with Scroll Bars
Valid when the device width is less than or equal to 768px.
| # | Title 1 | Title 2 | Title 3 |
|---|---|---|---|
| 0 | David | Jone | GOOD |
| 1 | Chuckie | Jone | BAD |
| 2 | Smith Jone | Lomi | Pictures are worth a thousand words, right? So Tom x 1,000. |
| 3 | Frank | Alice | PERFECT |
Show Code
import React from "react";
import {
Table,
TableBody,
TableCell,
TableHead,
TableRow,
} from 'funda-ui/Table';
// component styles
import 'funda-ui/Table/index.css';
const tableData = [
{name: 'David', friend: 'Jone', condition: 'GOOD'},
{name: 'Chuckie', friend: 'Jone', condition: 'BAD'},
{name: 'Smith Jone', friend: 'Lomi', condition: 'Pictures are worth a thousand words, right? So Tom x 1,000.'},
{name: 'Frank', friend: 'Alice', condition: 'PERFECT'},
];
export default () => {
return (
<>
<Table
responsive={false}
enhancedResponsiveWithScrollBar
tableClassName="table table-bordered"
>
<TableHead>
<TableRow>
<TableCell scope="col" nowrap>#</TableCell>
<TableCell scope="col" nowrap>Title 1</TableCell>
<TableCell scope="col" nowrap>Title 2</TableCell>
<TableCell scope="col" nowrap>Title 3</TableCell>
</TableRow>
</TableHead>
<TableBody>
{tableData.map((item: any, index: number) => {
return <TableRow
key={`row-${index}`}
data-key={`row-${index}`}
itemData={item}
>
<TableCell scope="row">{index}</TableCell>
<TableCell>{item.name}</TableCell>
<TableCell>{item.friend}</TableCell>
<TableCell>{item.condition}</TableCell>
</TableRow>
})}
</TableBody>
</Table>
</>
);
}e) No spacing
| # | Title 1 | Title 2 | Title 3 |
|---|---|---|---|
| 1 | David | Jone | Good |
| 2 | Chuckie | Jone | Pictures are worth a thousand words, right? So Tom x 1,000. |
| 3 | Hi There | Cool | |
Show Code
import React from "react";
import {
Table,
TableBody,
TableCell,
TableHead,
TableRow,
} from 'funda-ui/Table';
// component styles
import 'funda-ui/Table/index.css';
export default () => {
return (
<>
<Table
tableClassName="table-bordered" // remove class "table"
>
<TableHead>
<TableRow>
<TableCell scope="col" nowrap>#</TableCell>
<TableCell scope="col" nowrap>Title 1</TableCell>
<TableCell scope="col" nowrap>Title 2</TableCell>
<TableCell scope="col" nowrap>Title 3</TableCell>
</TableRow>
</TableHead>
<TableBody>
<TableRow active>
<TableCell scope="row">1</TableCell>
<TableCell>David</TableCell>
<TableCell>Jone</TableCell>
<TableCell>Good</TableCell>
</TableRow>
<TableRow>
<TableCell scope="row">2</TableCell>
<TableCell>Chuckie</TableCell>
<TableCell>Jone</TableCell>
<TableCell>Pictures are worth a thousand words, right? So Tom x 1,000.</TableCell>
</TableRow>
<TableRow>
<TableCell scope="row">3</TableCell>
<TableCell colSpan={2}>
Hi There
</TableCell>
<TableCell>Cool</TableCell>
</TableRow>
</TableBody>
</Table>
</>
);
}f) Prevent text in a table cell from wrapping
Use the following style:
thead th {
white-space: nowrap;
}Or using nowrap in <TableCell /> in <TableHead /> can also prevent text from wrapping automatically.
Header Group
| Designation | Apr-20 | May-20 | Jun-20 | ||||||
| Str | Slry | Avg./month | Str | Slry | Avg./month | Str | Slry | Avg./month | |
| Salary 1 | 246 | 38.8 | 0.16 | 245 | 35.04 | 0.14 | 208 | 32.22 | 0.15 |
| Salary 2 | 286 | 41.8 | 0.22 | 235 | 32.04 | 0.11 | 238 | 35.22 | 0.17 |
Show Code
import React from "react";
import {
Table,
TableBody,
TableCell,
TableHead,
TableRow,
} from 'funda-ui/Table';
// component styles
import 'funda-ui/Table/index.css';
export default () => {
const data = [
{
designation: "Salary 1",
headOffice: [246, 38.80, 0.16, 245, 35.04, 0.14, 208, 32.22, 0.15],
},
{
designation: "Salary 2",
headOffice: [286, 41.80, 0.22, 235, 32.04, 0.11, 238, 35.22, 0.17],
}
];
return (
<>
<Table tableClassName="table table-bordered table-striped align-middle">
<TableHead>
{/* First row: Large grouping */}
<TableRow>
<TableCell rowSpan={2} className="bg-dark text-light" nowrap>Designation</TableCell>
<TableCell colSpan={3} className="bg-dark text-light" align="center">Apr-20</TableCell>
<TableCell colSpan={3} className="bg-dark text-light" align="center">May-20</TableCell>
<TableCell colSpan={3} className="bg-dark text-light" align="center">Jun-20</TableCell>
</TableRow>
{/* Second row: Small groupings */}
<TableRow>
<TableCell className="bg-secondary text-light" nowrap>Str</TableCell>
<TableCell className="bg-secondary text-light" nowrap>Slry</TableCell>
<TableCell className="bg-secondary text-light" nowrap>Avg./month</TableCell>
<TableCell className="bg-secondary text-light" nowrap>Str</TableCell>
<TableCell className="bg-secondary text-light" nowrap>Slry</TableCell>
<TableCell className="bg-secondary text-light" nowrap>Avg./month</TableCell>
<TableCell className="bg-secondary text-light" nowrap>Str</TableCell>
<TableCell className="bg-secondary text-light" nowrap>Slry</TableCell>
<TableCell className="bg-secondary text-light" nowrap>Avg./month</TableCell>
</TableRow>
</TableHead>
<TableBody>
{data.map((row, idx) => (
<TableRow key={idx}>
<TableCell>{row.designation}</TableCell>
{row.headOffice.map((val, i) => (
<TableCell key={i}>{val}</TableCell>
))}
</TableRow>
))}
</TableBody>
</Table>
</>
);
}| Hello | Info | ||||
| FirstName | Last Name | Age | More Info | ||
| Visits | Status | Profile Progress | |||
| tanner | linsley | 24 | 100 | In Relationship | 50 |
| tandy | miller | 40 | 40 | Single | 80 |
| joe | dirte | 45 | 20 | Complicated | 10 |
Show Code
import React from "react";
import {
Table,
TableBody,
TableCell,
TableHead,
TableRow,
} from 'funda-ui/Table';
// component styles
import 'funda-ui/Table/index.css';
export default () => {
const data = [
{ firstName: "tanner", lastName: "linsley", age: 24, visits: 100, status: "In Relationship", progress: 50 },
{ firstName: "tandy", lastName: "miller", age: 40, visits: 40, status: "Single", progress: 80 },
{ firstName: "joe", lastName: "dirte", age: 45, visits: 20, status: "Complicated", progress: 10 },
];
return (
<>
<Table tableClassName="table table-bordered table-striped align-middle">
<TableHead>
{/* First row: Large grouping */}
<TableRow>
<TableCell colSpan={3} align="center" className="bg-dark text-light">Hello</TableCell>
<TableCell colSpan={3} align="center" className="bg-dark text-light">Info</TableCell>
</TableRow>
{/* Second row: Medium grouping */}
<TableRow>
<TableCell rowSpan={2} align="center" className="bg-secondary text-light align-middle">
FirstName
</TableCell>
<TableCell rowSpan={2} align="center" className="bg-secondary text-light align-middle">
Last Name
</TableCell>
<TableCell rowSpan={2} align="center" className="bg-secondary text-light align-middle">
Age
</TableCell>
<TableCell colSpan={3} align="center" className="bg-info text-dark">More Info</TableCell>
</TableRow>
{/* Third row: Bottommost level */}
<TableRow>
<TableCell align="center" className="bg-light text-dark">Visits</TableCell>
<TableCell align="center" className="bg-light text-dark">Status</TableCell>
<TableCell align="center" className="bg-light text-dark">Profile Progress</TableCell>
</TableRow>
</TableHead>
<TableBody>
{data.map((row, idx) => (
<TableRow key={idx}>
<TableCell>{row.firstName}</TableCell>
<TableCell>{row.lastName}</TableCell>
<TableCell>{row.age}</TableCell>
<TableCell>{row.visits}</TableCell>
<TableCell>{row.status}</TableCell>
<TableCell>{row.progress}</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</>
);
}Holy Grail Layout (3 columns)
| # | Title1 | Title2 | Title3 | Title4 | Title5 | Title6 | Title7 | Title8 | Title9 | Title10 | Title11 | Title12 | Title13 | Title14 | Title15 | Title16 | Title17 | Title18 | Title19 | Title20 | Title21 | Title22 | Title23 | Title24 | Title25 | Title26 | Title27 | Title28 | Title29 | Title30 | Title31 | Title32 | Title33 | Title34 | Title35 | Title36 | Title37 | Title38 | Title39 | Title40 | Title41 | Title42 | Title43 | Title44 | Title45 | Title46 | Title47 | Title48 | Title49 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| No.0 | 35 | 3 | 50 | 76 | 59 | 20 | 49 | 89 | 84 | 85 | 88 | 80 | 71 | 16 | 28 | 38 | 42 | 87 | 76 | 29 | 46 | 90 | 71 | 23 | 26 | 81 | 14 | 67 | 11 | 85 | 98 | 38 | 14 | 24 | 99 | 29 | 83 | 56 | 75 | 53 | 69 | 95 | 64 | 42 | 56 | 81 | 96 | 28 | 13 |
| No.1 | 65 | 60 | 43 | 15 | 68 | 45 | 58 | 43 | 40 | 0 | 44 | 92 | 42 | 52 | 83 | 81 | 32 | 75 | 88 | 18 | 20 | 80 | 46 | 61 | 29 | 67 | 23 | 25 | 36 | 26 | 66 | 61 | 5 | 1 | 2 | 40 | 18 | 93 | 93 | 36 | 64 | 92 | 46 | 33 | 25 | 23 | 70 | 13 | 28 |
| No.2 | 29 | 85 | 21 | 70 | 68 | 27 | 58 | 74 | 95 | 13 | 21 | 57 | 81 | 27 | 8 | 98 | 38 | 81 | 62 | 58 | 6 | 26 | 31 | 63 | 80 | 83 | 11 | 40 | 84 | 27 | 21 | 33 | 23 | 44 | 70 | 73 | 70 | 45 | 57 | 0 | 55 | 9 | 28 | 49 | 39 | 52 | 42 | 10 | 26 |
| No.3 | 79 | 93 | 27 | 51 | 25 | 71 | 33 | 61 | 44 | 32 | 93 | 8 | 0 | 40 | 95 | 42 | 41 | 25 | 37 | 24 | 19 | 93 | 5 | 67 | 7 | 23 | 81 | 53 | 11 | 66 | 92 | 48 | 31 | 40 | 8 | 74 | 95 | 98 | 49 | 53 | 11 | 34 | 6 | 82 | 60 | 9 | 46 | 59 | 19 |
| No.4 | 47 | 38 | 32 | 72 | 35 | 58 | 94 | 19 | 98 | 41 | 56 | 15 | 92 | 57 | 11 | 92 | 25 | 10 | 45 | 28 | 5 | 51 | 41 | 32 | 53 | 55 | 47 | 50 | 59 | 29 | 86 | 18 | 97 | 3 | 55 | 16 | 33 | 48 | 45 | 79 | 73 | 66 | 39 | 72 | 52 | 45 | 49 | 52 | 62 |
| No.5 | 36 | 27 | 21 | 85 | 92 | 40 | 75 | 77 | 89 | 16 | 54 | 45 | 43 | 5 | 91 | 33 | 50 | 56 | 19 | 13 | 67 | 52 | 80 | 81 | 30 | 36 | 16 | 52 | 73 | 69 | 90 | 23 | 75 | 9 | 72 | 93 | 75 | 45 | 29 | 11 | 18 | 3 | 51 | 31 | 83 | 66 | 40 | 46 | 4 |
| No.6 | 26 | 50 | 33 | 93 | 95 | 21 | 59 | 17 | 85 | 74 | 35 | 92 | 21 | 13 | 74 | 76 | 6 | 17 | 30 | 4 | 86 | 21 | 28 | 28 | 69 | 48 | 81 | 54 | 22 | 42 | 21 | 45 | 5 | 92 | 44 | 80 | 22 | 49 | 52 | 52 | 96 | 3 | 66 | 52 | 71 | 97 | 69 | 45 | 99 |
| No.7 | 43 | 41 | 56 | 12 | 48 | 36 | 75 | 49 | 62 | 75 | 18 | 53 | 52 | 43 | 5 | 70 | 3 | 89 | 33 | 63 | 17 | 31 | 56 | 29 | 61 | 61 | 93 | 30 | 11 | 83 | 4 | 3 | 0 | 31 | 12 | 41 | 67 | 87 | 2 | 34 | 11 | 47 | 81 | 59 | 71 | 28 | 22 | 97 | 64 |
| No.8 | 42 | 57 | 43 | 33 | 52 | 72 | 58 | 69 | 17 | 13 | 37 | 15 | 18 | 78 | 77 | 64 | 37 | 43 | 30 | 94 | 57 | 30 | 16 | 86 | 83 | 34 | 54 | 21 | 97 | 29 | 8 | 12 | 95 | 11 | 15 | 18 | 75 | 67 | 49 | 2 | 39 | 11 | 97 | 11 | 2 | 44 | 90 | 59 | 42 |
| No.9 | 31 | 17 | 3 | 4 | 38 | 40 | 81 | 74 | 28 | 47 | 6 | 6 | 17 | 47 | 51 | 42 | 30 | 58 | 84 | 83 | 93 | 84 | 64 | 47 | 60 | 80 | 96 | 84 | 2 | 81 | 70 | 69 | 97 | 6 | 22 | 25 | 66 | 9 | 15 | 26 | 62 | 65 | 35 | 82 | 7 | 76 | 72 | 36 | 98 |
| No.10 | 26 | 22 | 48 | 37 | 44 | 67 | 21 | 12 | 20 | 76 | 1 | 59 | 92 | 22 | 4 | 56 | 97 | 65 | 17 | 25 | 97 | 67 | 64 | 48 | 49 | 14 | 97 | 41 | 10 | 83 | 89 | 24 | 51 | 69 | 69 | 39 | 57 | 82 | 65 | 0 | 96 | 99 | 14 | 21 | 5 | 18 | 40 | 48 | 48 |
| No.11 | 31 | 83 | 70 | 26 | 86 | 40 | 93 | 83 | 31 | 32 | 69 | 48 | 89 | 48 | 46 | 3 | 61 | 10 | 76 | 85 | 24 | 31 | 83 | 13 | 31 | 46 | 27 | 46 | 63 | 77 | 68 | 16 | 80 | 72 | 31 | 76 | 55 | 48 | 45 | 70 | 59 | 72 | 60 | 18 | 36 | 81 | 43 | 65 | 55 |
| No.12 | 17 | 68 | 71 | 96 | 46 | 87 | 9 | 14 | 90 | 6 | 65 | 30 | 22 | 78 | 84 | 7 | 61 | 83 | 11 | 28 | 19 | 35 | 80 | 44 | 26 | 16 | 75 | 42 | 40 | 80 | 58 | 43 | 75 | 41 | 29 | 70 | 53 | 71 | 94 | 9 | 68 | 40 | 88 | 35 | 49 | 39 | 91 | 30 | 99 |
| No.13 | 28 | 62 | 61 | 55 | 65 | 77 | 32 | 70 | 22 | 99 | 29 | 7 | 24 | 38 | 67 | 99 | 6 | 4 | 80 | 94 | 51 | 1 | 64 | 97 | 7 | 23 | 60 | 70 | 97 | 76 | 97 | 1 | 58 | 96 | 84 | 93 | 44 | 28 | 99 | 20 | 37 | 92 | 78 | 43 | 4 | 28 | 94 | 91 | 44 |
| No.14 | 61 | 84 | 95 | 65 | 13 | 44 | 64 | 83 | 5 | 81 | 66 | 40 | 58 | 76 | 29 | 5 | 69 | 46 | 61 | 64 | 36 | 34 | 46 | 60 | 29 | 72 | 73 | 45 | 14 | 77 | 85 | 86 | 17 | 9 | 2 | 73 | 85 | 96 | 47 | 63 | 17 | 85 | 83 | 36 | 76 | 68 | 26 | 83 | 81 |
| No.15 | 92 | 98 | 70 | 86 | 66 | 82 | 69 | 67 | 69 | 56 | 13 | 57 | 36 | 89 | 89 | 53 | 25 | 93 | 24 | 96 | 16 | 65 | 31 | 44 | 28 | 64 | 35 | 24 | 85 | 26 | 14 | 64 | 35 | 68 | 26 | 6 | 23 | 69 | 90 | 29 | 41 | 65 | 14 | 65 | 40 | 22 | 52 | 95 | 41 |
| No.16 | 24 | 10 | 42 | 48 | 35 | 6 | 91 | 36 | 13 | 86 | 63 | 66 | 68 | 15 | 53 | 19 | 53 | 19 | 78 | 43 | 77 | 20 | 91 | 83 | 42 | 5 | 13 | 77 | 24 | 31 | 78 | 24 | 25 | 92 | 4 | 81 | 16 | 36 | 68 | 70 | 83 | 63 | 83 | 73 | 5 | 8 | 92 | 70 | 30 |
| No.17 | 66 | 74 | 37 | 47 | 53 | 51 | 40 | 57 | 31 | 51 | 71 | 62 | 36 | 79 | 63 | 40 | 31 | 85 | 87 | 99 | 25 | 17 | 95 | 23 | 76 | 81 | 97 | 42 | 92 | 9 | 20 | 82 | 73 | 0 | 80 | 85 | 29 | 38 | 1 | 84 | 5 | 22 | 29 | 86 | 72 | 56 | 26 | 27 | 15 |
| No.18 | 55 | 94 | 62 | 86 | 4 | 71 | 81 | 29 | 0 | 32 | 73 | 4 | 50 | 89 | 4 | 94 | 22 | 52 | 75 | 23 | 55 | 79 | 7 | 81 | 66 | 22 | 2 | 42 | 59 | 47 | 64 | 59 | 72 | 21 | 22 | 95 | 32 | 50 | 80 | 62 | 87 | 23 | 51 | 93 | 1 | 8 | 58 | 73 | 60 |
| No.19 | 58 | 51 | 83 | 20 | 63 | 64 | 6 | 69 | 36 | 14 | 6 | 63 | 48 | 47 | 1 | 9 | 57 | 78 | 15 | 25 | 78 | 85 | 25 | 92 | 36 | 64 | 45 | 14 | 53 | 59 | 4 | 63 | 55 | 98 | 91 | 16 | 83 | 19 | 67 | 21 | 94 | 75 | 29 | 5 | 90 | 85 | 47 | 13 | 45 |
Show Code [styles.scss]
/* ---------- Grid ----------- */
.demo-columns {
// display: grid;
// grid-template-columns: 250px auto 250px;
// grid-gap: .5rem;
display: flex;
flex-wrap: nowrap;
gap: .5rem;
.main {
flex-grow: 1; /* Adaptive width */
overflow: auto; /* Required, enable the scrollbar for content's scrollbar */
order: 2;
background: #8fe1ff;
}
.sidebar-first {
width: 250px;
background: #eee;
order: 1;
flex-shrink: 0; /* Prevent the left and right columns from being compressed */
}
.sidebar-second {
width: 250px;
order: 3;
background: #eee;
flex-shrink: 0; /* Prevent the left and right columns from being compressed */
}
}
/* ---------- Table Scrollable ----------- */
@mixin app-table-scrollbar($size: 10px) {
--syntable-scrollable-container-scrollbar-color: rgba(0, 0, 0, 0.2);
--syntable-scrollable-container-scrollbar-track: rgba(0, 0, 0, 0);
--syntable-scrollable-container-scrollbar-w: 10px;
--syntable-scrollable-container-scrollbar-h: 10px;
&::-webkit-scrollbar {
width: var(--syntable-scrollable-container-scrollbar-w);
height: var(--syntable-scrollable-container-scrollbar-h);
}
&::-webkit-scrollbar-thumb {
background: var(--syntable-scrollable-container-scrollbar-color);
}
&::-webkit-scrollbar-track {
background: var(--syntable-scrollable-container-scrollbar-track);
}
}
.app-table-scrollable-container {
.syntable__wrapper {
@include app-table-scrollbar();
position: relative;
overflow: auto;
width: 100%;
height: 200px;
thead tr > th {
position: sticky;
z-index: 2;
/* Stick the top and the left side */
top: 0;
left: 0;
&:first-child {
z-index: 3;
}
}
tbody > tr > th {
position: sticky;
/* Stick the left side */
left: 0;
z-index: 1;
}
}
}Show Code [index.tsx]
import React from "react";
import {
Table,
TableBody,
TableCell,
TableHead,
TableRow
} from 'funda-ui/Table';
// component styles
import 'funda-ui/Table/index.css';
function generateRandomData(rows: number, columns: number) {
const tableData = [];
for (let i = 0; i < rows; i++) {
const row = [];
for (let j = 0; j < columns; j++) {
row.push(Math.floor(Math.random() * 100)); // Generates a random number between 0 and 99
}
tableData.push(row);
}
return tableData;
}
const tableData = generateRandomData(20, 50);
export default () => {
return (
<>
<div className="demo-columns">
<div className="main">
<div className="app-table-scrollable-container">
<Table
responsive={false} // to use a custom horizontal scrollbar
cellAutoWidth // optional
tableClassName="table table-bordered table-striped mb-0 "
wrapperClassName=""
>
<TableHead>
<TableRow>
{Array.from({ length: tableData[0].length }).fill(0).map((x: any, j: number) => {
return <TableCell
key={`head-col-${j}`}
scope="col" nowrap
className="bg-dark text-light"
>
{j === 0 ? <>#</> : <>Title{j}</>}
</TableCell>
})}
</TableRow>
</TableHead>
<TableBody>
{tableData.map((item: any, index: number) => {
return <TableRow
key={`row-${index}`}
data-key={`row-${index}`}
itemData={item}
>
{Array.from({ length: tableData[0].length }).fill(0).map((x: any, j: number) => {
return <TableCell
key={`col-${j}`}
scope={j === 0 ? 'row' : null}
className={j === 0 ? 'bg-dark text-light' : null}
>
{j === 0 ? 'No.' + index : tableData[index][j]}
</TableCell>
})}
</TableRow>
})}
</TableBody>
</Table>
</div>
</div>
<div className="sidebar-first">Sidebar first: Fixed width</div>
<div className="sidebar-second">Sidebar second: Fixed width</div>
</div>
</>
);
}Sticky Table Headers (with custom scrollbar)
| # | Title1 | Title2 | Title3 | Title4 | Title5 | Title6 | Title7 | Title8 | Title9 | Title10 | Title11 | Title12 | Title13 | Title14 | Title15 | Title16 | Title17 | Title18 | Title19 | Title20 | Title21 | Title22 | Title23 | Title24 | Title25 | Title26 | Title27 | Title28 | Title29 | Title30 | Title31 | Title32 | Title33 | Title34 | Title35 | Title36 | Title37 | Title38 | Title39 | Title40 | Title41 | Title42 | Title43 | Title44 | Title45 | Title46 | Title47 | Title48 | Title49 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| No.0 | 35 | 3 | 50 | 76 | 59 | 20 | 49 | 89 | 84 | 85 | 88 | 80 | 71 | 16 | 28 | 38 | 42 | 87 | 76 | 29 | 46 | 90 | 71 | 23 | 26 | 81 | 14 | 67 | 11 | 85 | 98 | 38 | 14 | 24 | 99 | 29 | 83 | 56 | 75 | 53 | 69 | 95 | 64 | 42 | 56 | 81 | 96 | 28 | 13 |
| No.1 | 65 | 60 | 43 | 15 | 68 | 45 | 58 | 43 | 40 | 0 | 44 | 92 | 42 | 52 | 83 | 81 | 32 | 75 | 88 | 18 | 20 | 80 | 46 | 61 | 29 | 67 | 23 | 25 | 36 | 26 | 66 | 61 | 5 | 1 | 2 | 40 | 18 | 93 | 93 | 36 | 64 | 92 | 46 | 33 | 25 | 23 | 70 | 13 | 28 |
| No.2 | 29 | 85 | 21 | 70 | 68 | 27 | 58 | 74 | 95 | 13 | 21 | 57 | 81 | 27 | 8 | 98 | 38 | 81 | 62 | 58 | 6 | 26 | 31 | 63 | 80 | 83 | 11 | 40 | 84 | 27 | 21 | 33 | 23 | 44 | 70 | 73 | 70 | 45 | 57 | 0 | 55 | 9 | 28 | 49 | 39 | 52 | 42 | 10 | 26 |
| No.3 | 79 | 93 | 27 | 51 | 25 | 71 | 33 | 61 | 44 | 32 | 93 | 8 | 0 | 40 | 95 | 42 | 41 | 25 | 37 | 24 | 19 | 93 | 5 | 67 | 7 | 23 | 81 | 53 | 11 | 66 | 92 | 48 | 31 | 40 | 8 | 74 | 95 | 98 | 49 | 53 | 11 | 34 | 6 | 82 | 60 | 9 | 46 | 59 | 19 |
| No.4 | 47 | 38 | 32 | 72 | 35 | 58 | 94 | 19 | 98 | 41 | 56 | 15 | 92 | 57 | 11 | 92 | 25 | 10 | 45 | 28 | 5 | 51 | 41 | 32 | 53 | 55 | 47 | 50 | 59 | 29 | 86 | 18 | 97 | 3 | 55 | 16 | 33 | 48 | 45 | 79 | 73 | 66 | 39 | 72 | 52 | 45 | 49 | 52 | 62 |
| No.5 | 36 | 27 | 21 | 85 | 92 | 40 | 75 | 77 | 89 | 16 | 54 | 45 | 43 | 5 | 91 | 33 | 50 | 56 | 19 | 13 | 67 | 52 | 80 | 81 | 30 | 36 | 16 | 52 | 73 | 69 | 90 | 23 | 75 | 9 | 72 | 93 | 75 | 45 | 29 | 11 | 18 | 3 | 51 | 31 | 83 | 66 | 40 | 46 | 4 |
| No.6 | 26 | 50 | 33 | 93 | 95 | 21 | 59 | 17 | 85 | 74 | 35 | 92 | 21 | 13 | 74 | 76 | 6 | 17 | 30 | 4 | 86 | 21 | 28 | 28 | 69 | 48 | 81 | 54 | 22 | 42 | 21 | 45 | 5 | 92 | 44 | 80 | 22 | 49 | 52 | 52 | 96 | 3 | 66 | 52 | 71 | 97 | 69 | 45 | 99 |
| No.7 | 43 | 41 | 56 | 12 | 48 | 36 | 75 | 49 | 62 | 75 | 18 | 53 | 52 | 43 | 5 | 70 | 3 | 89 | 33 | 63 | 17 | 31 | 56 | 29 | 61 | 61 | 93 | 30 | 11 | 83 | 4 | 3 | 0 | 31 | 12 | 41 | 67 | 87 | 2 | 34 | 11 | 47 | 81 | 59 | 71 | 28 | 22 | 97 | 64 |
| No.8 | 42 | 57 | 43 | 33 | 52 | 72 | 58 | 69 | 17 | 13 | 37 | 15 | 18 | 78 | 77 | 64 | 37 | 43 | 30 | 94 | 57 | 30 | 16 | 86 | 83 | 34 | 54 | 21 | 97 | 29 | 8 | 12 | 95 | 11 | 15 | 18 | 75 | 67 | 49 | 2 | 39 | 11 | 97 | 11 | 2 | 44 | 90 | 59 | 42 |
| No.9 | 31 | 17 | 3 | 4 | 38 | 40 | 81 | 74 | 28 | 47 | 6 | 6 | 17 | 47 | 51 | 42 | 30 | 58 | 84 | 83 | 93 | 84 | 64 | 47 | 60 | 80 | 96 | 84 | 2 | 81 | 70 | 69 | 97 | 6 | 22 | 25 | 66 | 9 | 15 | 26 | 62 | 65 | 35 | 82 | 7 | 76 | 72 | 36 | 98 |
| No.10 | 26 | 22 | 48 | 37 | 44 | 67 | 21 | 12 | 20 | 76 | 1 | 59 | 92 | 22 | 4 | 56 | 97 | 65 | 17 | 25 | 97 | 67 | 64 | 48 | 49 | 14 | 97 | 41 | 10 | 83 | 89 | 24 | 51 | 69 | 69 | 39 | 57 | 82 | 65 | 0 | 96 | 99 | 14 | 21 | 5 | 18 | 40 | 48 | 48 |
| No.11 | 31 | 83 | 70 | 26 | 86 | 40 | 93 | 83 | 31 | 32 | 69 | 48 | 89 | 48 | 46 | 3 | 61 | 10 | 76 | 85 | 24 | 31 | 83 | 13 | 31 | 46 | 27 | 46 | 63 | 77 | 68 | 16 | 80 | 72 | 31 | 76 | 55 | 48 | 45 | 70 | 59 | 72 | 60 | 18 | 36 | 81 | 43 | 65 | 55 |
| No.12 | 17 | 68 | 71 | 96 | 46 | 87 | 9 | 14 | 90 | 6 | 65 | 30 | 22 | 78 | 84 | 7 | 61 | 83 | 11 | 28 | 19 | 35 | 80 | 44 | 26 | 16 | 75 | 42 | 40 | 80 | 58 | 43 | 75 | 41 | 29 | 70 | 53 | 71 | 94 | 9 | 68 | 40 | 88 | 35 | 49 | 39 | 91 | 30 | 99 |
| No.13 | 28 | 62 | 61 | 55 | 65 | 77 | 32 | 70 | 22 | 99 | 29 | 7 | 24 | 38 | 67 | 99 | 6 | 4 | 80 | 94 | 51 | 1 | 64 | 97 | 7 | 23 | 60 | 70 | 97 | 76 | 97 | 1 | 58 | 96 | 84 | 93 | 44 | 28 | 99 | 20 | 37 | 92 | 78 | 43 | 4 | 28 | 94 | 91 | 44 |
| No.14 | 61 | 84 | 95 | 65 | 13 | 44 | 64 | 83 | 5 | 81 | 66 | 40 | 58 | 76 | 29 | 5 | 69 | 46 | 61 | 64 | 36 | 34 | 46 | 60 | 29 | 72 | 73 | 45 | 14 | 77 | 85 | 86 | 17 | 9 | 2 | 73 | 85 | 96 | 47 | 63 | 17 | 85 | 83 | 36 | 76 | 68 | 26 | 83 | 81 |
| No.15 | 92 | 98 | 70 | 86 | 66 | 82 | 69 | 67 | 69 | 56 | 13 | 57 | 36 | 89 | 89 | 53 | 25 | 93 | 24 | 96 | 16 | 65 | 31 | 44 | 28 | 64 | 35 | 24 | 85 | 26 | 14 | 64 | 35 | 68 | 26 | 6 | 23 | 69 | 90 | 29 | 41 | 65 | 14 | 65 | 40 | 22 | 52 | 95 | 41 |
| No.16 | 24 | 10 | 42 | 48 | 35 | 6 | 91 | 36 | 13 | 86 | 63 | 66 | 68 | 15 | 53 | 19 | 53 | 19 | 78 | 43 | 77 | 20 | 91 | 83 | 42 | 5 | 13 | 77 | 24 | 31 | 78 | 24 | 25 | 92 | 4 | 81 | 16 | 36 | 68 | 70 | 83 | 63 | 83 | 73 | 5 | 8 | 92 | 70 | 30 |
| No.17 | 66 | 74 | 37 | 47 | 53 | 51 | 40 | 57 | 31 | 51 | 71 | 62 | 36 | 79 | 63 | 40 | 31 | 85 | 87 | 99 | 25 | 17 | 95 | 23 | 76 | 81 | 97 | 42 | 92 | 9 | 20 | 82 | 73 | 0 | 80 | 85 | 29 | 38 | 1 | 84 | 5 | 22 | 29 | 86 | 72 | 56 | 26 | 27 | 15 |
| No.18 | 55 | 94 | 62 | 86 | 4 | 71 | 81 | 29 | 0 | 32 | 73 | 4 | 50 | 89 | 4 | 94 | 22 | 52 | 75 | 23 | 55 | 79 | 7 | 81 | 66 | 22 | 2 | 42 | 59 | 47 | 64 | 59 | 72 | 21 | 22 | 95 | 32 | 50 | 80 | 62 | 87 | 23 | 51 | 93 | 1 | 8 | 58 | 73 | 60 |
| No.19 | 58 | 51 | 83 | 20 | 63 | 64 | 6 | 69 | 36 | 14 | 6 | 63 | 48 | 47 | 1 | 9 | 57 | 78 | 15 | 25 | 78 | 85 | 25 | 92 | 36 | 64 | 45 | 14 | 53 | 59 | 4 | 63 | 55 | 98 | 91 | 16 | 83 | 19 | 67 | 21 | 94 | 75 | 29 | 5 | 90 | 85 | 47 | 13 | 45 |
Show Code [styles.scss]
/* ---------- Table Scrollable ----------- */
@mixin app-table-scrollbar($size: 10px) {
--syntable-scrollable-container-scrollbar-color: rgba(0, 0, 0, 0.2);
--syntable-scrollable-container-scrollbar-track: rgba(0, 0, 0, 0);
--syntable-scrollable-container-scrollbar-w: 10px;
--syntable-scrollable-container-scrollbar-h: 10px;
&::-webkit-scrollbar {
width: var(--syntable-scrollable-container-scrollbar-w);
height: var(--syntable-scrollable-container-scrollbar-h);
}
&::-webkit-scrollbar-thumb {
background: var(--syntable-scrollable-container-scrollbar-color);
}
&::-webkit-scrollbar-track {
background: var(--syntable-scrollable-container-scrollbar-track);
}
}
.app-table-scrollable-container {
.syntable__wrapper {
@include app-table-scrollbar();
position: relative;
overflow: auto;
width: 100%;
height: 200px;
thead tr > th {
position: sticky;
z-index: 2;
/* Stick the top and the left side */
top: 0;
left: 0;
&:first-child {
z-index: 3;
}
}
tbody > tr > th {
position: sticky;
/* Stick the left side */
left: 0;
z-index: 1;
}
}
}Show Code [index.tsx]
import React from "react";
import {
Table,
TableBody,
TableCell,
TableHead,
TableRow
} from 'funda-ui/Table';
// component styles
import 'funda-ui/Table/index.css';
function generateRandomData(rows: number, columns: number) {
const tableData = [];
for (let i = 0; i < rows; i++) {
const row = [];
for (let j = 0; j < columns; j++) {
row.push(Math.floor(Math.random() * 100)); // Generates a random number between 0 and 99
}
tableData.push(row);
}
return tableData;
}
const tableData = generateRandomData(20, 50);
export default () => {
return (
<>
<div className="app-table-scrollable-container">
<Table
responsive={false} // to use a custom horizontal scrollbar
cellAutoWidth // optional
tableClassName="table table-bordered table-striped mb-0 "
wrapperClassName=""
>
<TableHead>
<TableRow>
{Array.from({ length: tableData[0].length }).fill(0).map((x: any, j: number) => {
return <TableCell
key={`head-col-${j}`}
scope="col" nowrap
className="bg-dark text-light"
>
{j === 0 ? <>#</> : <>Title{j}</>}
</TableCell>
})}
</TableRow>
</TableHead>
<TableBody>
{tableData.map((item: any, index: number) => {
return <TableRow
key={`row-${index}`}
data-key={`row-${index}`}
itemData={item}
>
{Array.from({length: tableData[0].length}).fill(0).map((x: any, j: number) => {
return <TableCell
key={`col-${j}`}
scope={j === 0 ? 'row' : null}
className={j === 0 ? 'bg-dark text-light' : null}
>
{j=== 0 ? 'No.' + index : tableData[index][j]}
</TableCell>
})}
</TableRow>
})}
</TableBody>
</Table>
</div>
</>
);
}Table Column Group
| # | Name | Friend | Condition |
|---|---|---|---|
| 0 | David | Jone | GOOD |
| 1 | Chuckie | Jone | BAD |
| 2 | Smith Jone | Lomi | Pictures are worth a thousand words, right? So Tom x 1,000. |
| 3 | Frank | Alice | PERFECT |
Show Code
import React from "react";
import {
Table,
TableBody,
TableCell,
TableHead,
TableRow,
TableColgroup,
} from 'funda-ui/Table';
// component styles
import 'funda-ui/Table/index.css';
const tableData = [
{name: 'David', friend: 'Jone', condition: 'GOOD'},
{name: 'Chuckie', friend: 'Jone', condition: 'BAD'},
{name: 'Smith Jone', friend: 'Lomi', condition: 'GOOD'},
{name: 'Frank', friend: 'Alice', condition: 'PERFECT'},
];
export default () => {
return (
<>
<Table
colGroup
tableClassName="table"
>
<TableColgroup length={4} />
<TableHead>
<TableRow>
<TableCell scope="col" nowrap>#</TableCell>
<TableCell scope="col" nowrap>Name</TableCell>
<TableCell scope="col" nowrap>Friend</TableCell>
<TableCell scope="col" nowrap>Condition</TableCell>
</TableRow>
</TableHead>
<TableBody>
{tableData.map((item: any, index: number) => {
return <TableRow
key={`row-${index}`}
data-key={`row-${index}`}
itemData={item}
>
<TableCell scope="row">{index}</TableCell>
<TableCell>{item.name}</TableCell>
<TableCell>{item.friend}</TableCell>
<TableCell>{item.condition}</TableCell>
</TableRow>
})}
</TableBody>
</Table>
</>
);
}Filter Table
To interact with data is required using the
dataproperty of<Table />anditemDataproperty of<TableRow />.
It is valid when filterFields exists. You can set more properties, such as: onChangeFilter.
| # | Name | Friend | Condition |
|---|---|---|---|
| 0 | David | Jone | GOOD |
| 1 | Chuckie | Jone | BAD |
| 2 | Smith Jone | Lomi | Pictures are worth a thousand words, right? So Tom x 1,000. |
| 3 | Frank | Alice | PERFECT |
Show Code
import React from "react";
import {
Table,
TableBody,
TableCell,
TableHead,
TableRow,
TableCaption,
// filter
TableFilter,
} from 'funda-ui/Table';
// component styles
import 'funda-ui/Table/index.css';
const tableData = [
{name: 'David', friend: 'Jone', condition: 'GOOD'},
{name: 'Chuckie', friend: 'Jone', condition: 'BAD'},
{name: 'Smith Jone', friend: 'Lomi', condition: 'GOOD'},
{name: 'Frank', friend: 'Alice', condition: 'PERFECT'},
];
export default () => {
return (
<>
<Table
tableClassName="table"
data={tableData}
filterFields={['name', 'friend']}
onChangeFilter={(fetchData: any[]) => {
console.log(fetchData);
}}
>
<TableCaption>
<TableFilter
placeholder="Enter keywords..."
/>
</TableCaption>
<TableHead>
<TableRow>
<TableCell scope="col" nowrap>#</TableCell>
<TableCell scope="col" nowrap>Name</TableCell>
<TableCell scope="col" nowrap>Friend</TableCell>
<TableCell scope="col" nowrap>Condition</TableCell>
</TableRow>
</TableHead>
<TableBody>
{tableData.map((item: any, index: number) => {
return <TableRow
key={`row-${index}`}
data-key={`row-${index}`}
itemData={item}
>
<TableCell scope="row">{index}</TableCell>
<TableCell>{item.name}</TableCell>
<TableCell>{item.friend}</TableCell>
<TableCell>{item.condition}</TableCell>
</TableRow>
})}
</TableBody>
</Table>
</>
);
}Row selection (multiple rows)
To interact with data is required using the
dataproperty of<Table />anditemDataproperty of<TableRow />.
It is valid when rowSelectable is "true". You can set more properties, such as: onChangeRowSelect, dataSelected.
a) Normal
| # | Name | Friend | Condition |
|---|
Show Code
import React, { useRef, useState, useEffect } from "react";
import {
Table,
TableBody,
TableCell,
TableHead,
TableRow,
// utils
ToggleSelection,
} from 'funda-ui/Table';
// component styles
import 'funda-ui/Table/index.css';
export default () => {
const [tableData, setTableData] = useState<any[]>([]);
const tableSelectAllRef = useRef<any>(null);
useEffect(() => {
// test async
setTableData([
{ name: 'David', friend: 'Jone', condition: 'GOOD' },
{ name: 'Chuckie', friend: 'Jone', condition: 'BAD' },
{ name: 'Smith Jone', friend: 'Lomi', condition: 'GOOD' },
{ name: 'Frank', friend: 'Alice', condition: 'PERFECT' },
]);
}, []);
return (
<>
<Table
rowSelectable
tableClassName="table"
data={tableData}
// dataSelected={[1,3]}
onChangeRowSelect={(fetchData: any[]) => {
console.log(fetchData);
}}
>
<TableHead>
<TableRow>
<TableCell scope="col" nowrap style={{width: '25px'}}>
{/** Checkbox */}
<div className="checkbox-indeterminate">
<ToggleSelection row={-1} contentRef={tableSelectAllRef} />
</div>
</TableCell>
<TableCell scope="col" nowrap>#</TableCell>
<TableCell scope="col" nowrap>Name</TableCell>
<TableCell scope="col" nowrap>Friend</TableCell>
<TableCell scope="col" nowrap>Condition</TableCell>
</TableRow>
</TableHead>
<TableBody>
{tableData.map((item: any, index: number) => {
return <TableRow
key={`row-${index}`}
data-key={`row-${index}`}
itemData={item}
>
<TableCell scope="row">
{/** Checkbox */}
<div className="checkbox-indeterminate">
<ToggleSelection
row={index}
checked={index === 1 || index === 2}
onChange={(e: React.MouseEvent, val: boolean, fetchData: any[]) => {
// Initialize indeterminate status of all checkboxes
if (tableSelectAllRef.current) {
if (fetchData.length > 0 || fetchData.length < tableData.length) tableSelectAllRef.current.indeterminate(true);
if (fetchData.length === 0 || fetchData.length === tableData.length) tableSelectAllRef.current.indeterminate(false);
if (fetchData.length === 0) tableSelectAllRef.current.setSelectAll(false);
if (fetchData.length === tableData.length) tableSelectAllRef.current.setSelectAll(true);
}
}}
/>
</div>
</TableCell>
<TableCell scope="row">{index}</TableCell>
<TableCell>{item.name}</TableCell>
<TableCell>{item.friend}</TableCell>
<TableCell>{item.condition}</TableCell>
</TableRow>
})}
</TableBody>
</Table>
</>
);
}b) Use radio instead of Checkbox
| # | Name | Friend | Condition |
|---|
Show Code
import React, { useRef, useState, useEffect } from "react";
import {
Table,
TableBody,
TableCell,
TableHead,
TableRow,
// utils
ToggleSelection,
} from 'funda-ui/Table';
// component styles
import 'funda-ui/Table/index.css';
export default () => {
const [tableData, setTableData] = useState<any[]>([]);
const tableSelectAllRef = useRef<any>(null);
useEffect(() => {
// test async
setTableData([
{ name: 'David', friend: 'Jone', condition: 'GOOD' },
{ name: 'Chuckie', friend: 'Jone', condition: 'BAD' },
{ name: 'Smith Jone', friend: 'Lomi', condition: 'GOOD' },
{ name: 'Frank', friend: 'Alice', condition: 'PERFECT' },
]);
}, []);
return (
<>
<Table
rowSelectable
tableClassName="table"
data={tableData}
dataSelected={[2]}
onChangeRowSelect={(fetchData: any[]) => {
console.log(fetchData);
}}
>
<TableHead>
<TableRow>
<TableCell scope="col" nowrap style={{width: '25px'}}></TableCell>
<TableCell scope="col" nowrap>#</TableCell>
<TableCell scope="col" nowrap>Name</TableCell>
<TableCell scope="col" nowrap>Friend</TableCell>
<TableCell scope="col" nowrap>Condition</TableCell>
</TableRow>
</TableHead>
<TableBody>
{tableData.map((item: any, index: number) => {
return <TableRow
key={`row-${index}`}
data-key={`row-${index}`}
itemData={item}
>
<TableCell scope="row">
{/** Checkbox */}
<div className="checkbox-indeterminate">
<ToggleSelection
useRadio
row={index}
/>
</div>
</TableCell>
<TableCell scope="row">{index}</TableCell>
<TableCell>{item.name}</TableCell>
<TableCell>{item.friend}</TableCell>
<TableCell>{item.condition}</TableCell>
</TableRow>
})}
</TableBody>
</Table>
</>
);
}c) Set the checkbox of the specified rows
Set the value of the checkbox externally separately.
Setting rows 1 and 3
| # | Name | Friend | Condition |
|---|
Show Code
import React, { useRef, useState, useEffect } from "react";
import {
Table,
TableBody,
TableCell,
TableHead,
TableRow,
// utils
ToggleSelection,
} from 'funda-ui/Table';
// component styles
import 'funda-ui/Table/index.css';
export default () => {
const [tableData, setTableData] = useState<any[]>([]);
const tableSelectAllRef = useRef<any>(null);
const tablePrRowSelectAllRef = useRef<any[]>([]);
useEffect(() => {
// test async
setTableData([
{ name: 'David', friend: 'Jone', condition: 'GOOD' },
{ name: 'Chuckie', friend: 'Jone', condition: 'BAD' },
{ name: 'Smith Jone', friend: 'Lomi', condition: 'GOOD' },
{ name: 'Frank', friend: 'Alice', condition: 'PERFECT' },
]);
}, []);
return (
<>
<a
href="#"
onClick={(e: React.MouseEvent) => {
e.preventDefault();
if (tablePrRowSelectAllRef.current) {
tablePrRowSelectAllRef.current.forEach((node: any, index: number) => {
if (node.control()?.dataset.row == '1' || node.control()?.dataset.row == '3') {
node.set(true);
}
});
}
if (tableSelectAllRef.current) {
tableSelectAllRef.current.indeterminate(false);
tableSelectAllRef.current.setSelectAll(false);
}
}}
>Setting rows 1 and 3</a>
<Table
rowSelectable
tableClassName="table"
data={tableData}
// dataSelected={[1,3]}
onChangeRowSelect={(fetchData: any[]) => {
console.log(fetchData);
}}
>
<TableHead>
<TableRow>
<TableCell scope="col" style={{width: '25px'}}>
{/** Checkbox */}
<div className="checkbox-indeterminate">
<ToggleSelection row={-1} contentRef={tableSelectAllRef} />
</div>
</TableCell>
<TableCell scope="col" >#</TableCell>
<TableCell scope="col" nowrap>Name</TableCell>
<TableCell scope="col" nowrap>Friend</TableCell>
<TableCell scope="col" nowrap>Condition</TableCell>
</TableRow>
</TableHead>
<TableBody>
{tableData.map((item: any, index: number) => {
return <TableRow
key={`row-${index}`}
data-key={`row-${index}`}
itemData={item}
>
<TableCell scope="row">
{/** Checkbox */}
<div className="checkbox-indeterminate">
<ToggleSelection
row={index}
contentRef={(node: any) => {
if (node) {
tablePrRowSelectAllRef.current.push(node);
}
}}
onChange={(e: React.MouseEvent, val: boolean, fetchData: any[]) => {
// Initialize indeterminate status of all checkboxes
if (tableSelectAllRef.current) {
if (fetchData.length > 0 || fetchData.length < tableData.length) tableSelectAllRef.current.indeterminate(true);
if (fetchData.length === 0 || fetchData.length === tableData.length) tableSelectAllRef.current.indeterminate(false);
if (fetchData.length === 0) tableSelectAllRef.current.setSelectAll(false);
if (fetchData.length === tableData.length) tableSelectAllRef.current.setSelectAll(true);
}
}}
/>
</div>
</TableCell>
<TableCell scope="row">{index}</TableCell>
<TableCell>{item.name}</TableCell>
<TableCell>{item.friend}</TableCell>
<TableCell>{item.condition}</TableCell>
</TableRow>
})}
</TableBody>
</Table>
</>
);
}d) Matching and filtering checkboxes based on the fields of a column
For example, based on an ID column, if the IDs match, select all rows with the same ID. Note that you should not use onChangeRowSelect to set STATE for this.
| # | ID | Name | No | Condition |
|---|
Show Code
import React, { useRef, useState, useEffect } from "react";
import {
Table,
TableBody,
TableCell,
TableHead,
TableRow,
// utils
ToggleSelection,
} from 'funda-ui/Table';
// component styles
import 'funda-ui/Table/index.css';
export default () => {
const [tableData, setTableData] = useState<any[]>([]);
const tableSelectAllRef = useRef<any>(null);
const tablePrRowSelectAllRef = useRef<any[]>([]);
const [selectIds, setSelectIds] = useState<number[]>([]);
const tableCheckRef = useRef<Map<string, any>>(new Map());
const getItem = (item: any) => {
return tableData.find((v: any) => v.name === item.name);
};
const getNewSelectedIds = (currentSelectedIds: number[], isChecked: boolean, targetItem: any) => {
const targetSettleId = getItem(targetItem)?.id;
// If there is no "id", return the original list directly (or add or remove items based on isChecked).
if (!targetSettleId) return currentSelectedIds;
// Find all names that belong to the same "id".
const relatedIds = tableData
.filter(listItem => getItem(listItem)?.id === targetSettleId)
.map(listItem => listItem.name);
if (isChecked) {
// Merge and remove duplicates
return Array.from(new Set([...currentSelectedIds, ...relatedIds]));
} else {
// Exclude all associated IDs
return currentSelectedIds.filter(id => !relatedIds.includes(id));
}
};
useEffect(() => {
// test async
setTableData([
{ name: 'David', id: 6655737, no: 1, condition: 'GOOD' },
{ name: 'Lucy', id: 6655737, no: 2, condition: 'GOOD' },
{ name: 'Chuckie', id: 145635, no: 3, condition: 'BAD' },
{ name: 'Smith', id: 6655737, no: 4, condition: 'GOOD' },
{ name: 'Frank', id: 2335623, no: 5, condition: 'PERFECT' },
{ name: 'Leo', id: 145635, no: 6, condition: 'NOTHING' },
]);
}, []);
return (
<>
<Table
rowSelectable
tableClassName="table"
data={tableData}
>
<TableHead>
<TableRow>
<TableCell scope="col" style={{width: '25px'}}>
{/** Checkbox */}
<div className="checkbox-indeterminate">
<ToggleSelection
row={-1}
contentRef={tableSelectAllRef}
onChange={(e: React.MouseEvent, val: boolean) => {
if (val) {
// Select All: Retrieves all names in the current list.
const allIds = tableData.map((item: any) => item.name);
setSelectIds(allIds);
// Synchronize UI: Manually select all checkboxes in the list.
tableData.forEach((item: any) => {
const checkRef = tableCheckRef.current.get(item.no.toString());
if (checkRef) {
checkRef.set(true);
}
});
} else {
// Unselect all
setSelectIds([]);
// Synchronize UI: Manually uncheck all checkboxes in the list.
tableData.forEach((item: any) => {
const checkRef = tableCheckRef.current.get(item.no.toString());
if (checkRef) {
checkRef.set(false);
}
});
}
}}
/>
</div>
</TableCell>
<TableCell scope="col" >#</TableCell>
<TableCell scope="col" nowrap>ID</TableCell>
<TableCell scope="col" nowrap>Name</TableCell>
<TableCell scope="col" nowrap>No</TableCell>
<TableCell scope="col" nowrap>Condition</TableCell>
</TableRow>
</TableHead>
<TableBody>
{tableData.map((item: any, index: number) => {
return <TableRow
key={`row-${index}`}
data-key={`row-${index}`}
itemData={item}
>
<TableCell scope="row">
{/** Checkbox */}
<ToggleSelection
row={index}
contentRef={(node: any) => {
if (node) {
tableCheckRef.current.set(item.no.toString(), node);
}
}}
onChange={(e: React.MouseEvent, val: boolean, fetchData: any[]) => {
// 1. Compute a new selected ID array
setSelectIds((prev) => {
const nextIds = getNewSelectedIds(prev, val, item);
// 2. Manual UI synchronization: Because it involves external control and linkage, it is necessary to manually set the state of checkboxes with the same "id" to be consistent.
const targetId = getItem(item)?.id;
if (targetId) {
tableData.forEach((listItem: any) => {
if (getItem(listItem)?.id === targetId) {
const checkRef = tableCheckRef.current.get(listItem.no.toString());
if (checkRef) {
checkRef.set(val);
}
}
});
}
// 3. Initialize indeterminate status of all checkboxes
if (tableSelectAllRef.current) {
if (nextIds.length > 0 || nextIds.length < tableData.length) tableSelectAllRef.current.indeterminate(true);
if (nextIds.length === 0 || nextIds.length === tableData.length) tableSelectAllRef.current.indeterminate(false);
if (nextIds.length === 0) tableSelectAllRef.current.setSelectAll(false);
if (nextIds.length === tableData.length) tableSelectAllRef.current.setSelectAll(true);
}
return nextIds;
});
}}
/>
</div>
</TableCell>
<TableCell scope="row">{index}</TableCell>
<TableCell>{item.id}</TableCell>
<TableCell>{item.name}</TableCell>
<TableCell>{item.no}</TableCell>
<TableCell>{item.condition}</TableCell>
</TableRow>
})}
</TableBody>
</Table>
<p><small>{selectIds.join(',')}</small></p>
</>
);
}Drag and Drop Sort Rows
To interact with data is required using the
dataproperty of<Table />anditemDataproperty of<TableRow />.
It is valid when rowDraggable exists. You can set more properties, such as: onRowDrag.
| # | Name | Friend | Condition |
|---|---|---|---|
| 0 | David | Jone | GOOD |
| 1 | Chuckie | Jone | BAD |
| 2 | Smith Jone | Lomi | Pictures are worth a thousand words, right? So Tom x 1,000. |
| 3 | Frank | Alice | PERFECT |
Show Code
import React, { useState } from "react";
import {
Table,
TableBody,
TableCell,
TableHead,
TableRow,
// drag and drop
DragHandleSprite,
} from 'funda-ui/Table';
// component styles
import 'funda-ui/Table/index.css';
const tableData = [
{name: 'David', friend: 'Jone', condition: 'GOOD'},
{name: 'Chuckie', friend: 'Jone', condition: 'BAD'},
{name: 'Smith Jone', friend: 'Lomi', condition: 'GOOD'},
{name: 'Frank', friend: 'Alice', condition: 'PERFECT'},
];
export default () => {
const [sortedData, setSortedData] = useState<any[]>([]);
return (
<>
<Table
tableClassName="table table-bordered"
data={tableData}
rowDraggable
onRowDrag={(dragStart, dragEnd) => {
if ( dragStart !== null ) dragStart((el: HTMLTableRowElement, order: number[], data: any[])=> {
console.log('dragStart: ', el, order, data);
});
if ( dragEnd !== null ) dragEnd((el: HTMLTableRowElement, order: number[], data: any[])=> {
console.log('dragEnd: ', el, order, data);
setSortedData(data); // DO NOT UPDATE `tableData`
});
}}
>
<TableHead>
<TableRow>
<TableCell scope="col" nowrap>#</TableCell>
<TableCell scope="col" nowrap>Name</TableCell>
<TableCell scope="col" nowrap>Friend</TableCell>
<TableCell scope="col" nowrap>Condition</TableCell>
</TableRow>
</TableHead>
<TableBody>
{tableData.map((item: any, index: number) => {
return <TableRow
key={`row-${index}`}
data-key={`row-${index}`}
itemData={item}
>
<TableCell scope="row"><DragHandleSprite /> {index}</TableCell>
<TableCell>{item.name}</TableCell>
<TableCell>{item.friend}</TableCell>
<TableCell>{item.condition}</TableCell>
</TableRow>
})}
</TableBody>
</Table>
<small>{JSON.stringify(sortedData)}</small>
</>
);
}Sortable Table
To interact with data is required using the
dataproperty of<Table />anditemDataproperty of<TableRow />.
It is valid when colSortable exists. You can set more properties, such as: onColSort.
sortBy allows you to sort with multiple column combinations. such as:
sortBy: (handleProcess: Function, filterType: string, inverse: boolean) => (a: Element, b: Element) => {
// Custom comparison logic
let v1 = a.textContent, v2 = b.textContent;
if (filterType === 'number') {
v1 = parseFloat(v1);
v2 = parseFloat(v2);
}
let result = 0;
if (filterType === 'text') {
result = v1.localeCompare(v2);
} else {
result = v1 - v2;
}
// Apply display animation and status updates
handleProcess();
return inverse ? -result : result;
}| # | Money | Name | No. | Date1 | Date2 |
|---|---|---|---|---|---|
| 0 | $55.134 | David Lin | 3453434 | 2012-09-25T12:10:46+00:00 | May 22, 2003 |
| 1 | $-24.0 | Foristin | +6.6 | 2011-02-26T12:10:46+00:00 | July 22, 2016 |
| 2 | $255.12 | Co Cheey | -2324.343 | 2013-09-10T12:10:46+00:00 | September 13, 2013 |
| 3 | $21.134 | Foristin | -34789.34 | 2018-09-24T12:10:46+00:00 | January 2, 2019 |
| 4 | $3454.134 | Alice | +224.5 | 2011-09-21T12:10:46+00:00 | December 1, 2018 |
| 5 | $224.0 | Wooli | +33.6 | 2011-02-26T12:10:46+00:00 | July 22, 2017 |
| 6 | $11.134 | Foristin | -1789.34 | 2018-09-24T12:10:46+00:00 | January 2, 2024 |
| 7 | $356.2 | Spiter Low | 278.23487 | 2019-01-01T12:10:46+00:00 | July 28, 2017 |
| 8 | $154.134 | Foristin | +524.5 | 2011-09-21T12:10:46+00:00 | December 1, 2011 |
| 9 | $256.2 | Foristin | 178.23487 | 2019-01-01T12:10:46+00:00 | July 28, 2014 |
Show Code
import React from "react";
import {
Table,
TableBody,
TableCell,
TableHead,
TableRow,
// sort
SortSprite,
} from 'funda-ui/Table';
// component styles
import 'funda-ui/Table/index.css';
const tableData = [
{money: "$55.134", name: "David Lin", no: "3453434", date1: "2012-09-25T12:10:46+00:00", date2: "May 22, 2003"},
{money: "$-24.0", name: "Foristin", no: "+6.6", date1: "2011-02-26T12:10:46+00:00", date2: "July 22, 2016"},
{money: "$255.12", name: "Co Cheey", no: "-2324.343", date1: "2013-09-10T12:10:46+00:00", date2: "September 13, 2013"},
{money: "$21.134", name: "Foristin", no: "-34789.34", date1: "2018-09-24T12:10:46+00:00", date2: "January 2, 2019"},
{money: "$3454.134", name: "Alice", no: "+224.5", date1: "2011-09-21T12:10:46+00:00", date2: "December 1, 2018"},
{money: "$224.0", name: "Wooli", no: "+33.6", date1: "2011-02-26T12:10:46+00:00", date2: "July 22, 2017"},
{money: "$11.134", name: "Foristin", no: "-1789.34", date1: "2018-09-24T12:10:46+00:00", date2: "January 2, 2024"},
{money: "$356.2", name: "Spiter Low", no: "278.23487", date1: "2019-01-01T12:10:46+00:00", date2: "July 28, 2017"},
{money: "$154.134", name: "Foristin", no: "+524.5", date1: "2011-09-21T12:10:46+00:00", date2: "December 1, 2011"},
{money: "$256.2", name: "Foristin", no: "178.23487", date1: "2019-01-01T12:10:46+00:00", date2: "July 28, 2014"},
];
export default () => {
return (
<>
<Table
tableClassName="table table-bordered"
data={tableData}
colSortable
onColSort={(fetchData: any[]) => {
console.log(fetchData);
}}
>
<TableHead>
<TableRow>
<TableCell scope="col" nowrap>#</TableCell>
<TableCell scope="col" nowrap>Money <SortSprite fieldType="number" /></TableCell>
<TableCell scope="col" nowrap>Name
<SortSprite
fieldType="text"
isReverse
sortBy={(handleProcess: Function, filterType: string, inverse: boolean) => {
// Sort by "Name" in regular order first, and then by "No." in the Name group
return (a: Element, b: Element) => {
const trA: any = a.closest('tr');
const trB: any = b.closest('tr');
const getText = (tr: Element, col: number) => {
return tr.querySelector(`[data-table-col="${col}"]`)?.textContent?.trim().toLowerCase() || "";
};
const nameA = getText(trA, 2);
const nameB = getText(trB, 2);
const noA = parseFloat(getText(trA, 3).replace(/[^0-9.+-]/g, ""));
const noB = parseFloat(getText(trB, 3).replace(/[^0-9.+-]/g, ""));
const nameCompare = nameA.localeCompare(nameB, "zh-CN", { sensitivity: "base" });
if (nameCompare !== 0) return nameCompare;
// Apply display animation and status updates
handleProcess();
return inverse ? noB - noA : noA - noB;
}
}}
/>
</TableCell>
<TableCell scope="col" nowrap>No. <SortSprite fieldType="number" /></TableCell>
<TableCell scope="col" nowrap>Date1 <SortSprite fieldType="date" /></TableCell>
<TableCell scope="col" nowrap>Date2 <SortSprite fieldType="date" /></TableCell>
</TableRow>
</TableHead>
<TableBody>
{tableData.map((item: any, index: number) => {
return <TableRow
key={`row-${index}`}
data-key={`row-${index}`}
itemData={item}
>
<TableCell scope="row">{index}</TableCell>
<TableCell>{item.money}</TableCell>
<TableCell>{item.name}</TableCell>
<TableCell>{item.no}</TableCell>
<TableCell>{item.date1}</TableCell>
<TableCell>{item.date2}</TableCell>
</TableRow>
})}
</TableBody>
</Table>
</>
);
}Table Cell Editable
| # | Money | Name | No. | Date1 | Date2 |
|---|
Show Code
import { useEffect, useState, useRef } from "react";
// bootstrap components
import {
Table,
TableBody,
TableCell,
TableHead,
TableRow,
// utils
ToggleSelection,
} from 'funda-ui/Table';
import Date from 'funda-ui/Date';
// component styles
import 'funda-ui/Table/index.css';
import 'funda-ui/Date/index.css';
const EditableCellInput = (props: any) => {
const {
rowIndex,
colIndex,
defaultValue,
onChange
} = props;
const inputWrapperRef = useRef<HTMLDivElement>(null);
const [controlShow, setControlShow] = useState<boolean>(false);
const [changeContent, setChangeContent] = useState<boolean>(false);
const [curVal, setCurVal] = useState<string>(defaultValue);
function handleClick(e: React.MouseEvent) {
e.preventDefault();
setControlShow(true);
setChangeContent(true);
setTimeout(() => {
if (inputWrapperRef.current) (inputWrapperRef.current.querySelector('.form-control') as any).focus();
}, 0);
}
return (
<>
<div onClick={handleClick} style={{cursor: 'pointer', minWidth: '20px', minHeight: '20px'}}>{changeContent ? <><i className="fa-solid fa-circle-notch fa-spin"></i></> : curVal === '' ? '-' : curVal}</div>
{controlShow ? <>
<div ref={inputWrapperRef} className={`position-absolute z-1 top-0 start-0`} style={{ width: '150px' }}>
<input
value={curVal === '-' ? '' : curVal}
placeholder="Enter"
className="form-control"
data-row={`${rowIndex}`}
data-col={colIndex}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
const newValue = e.target.value;
setCurVal(newValue);
onChange?.(e.target.dataset.row, e.target.dataset.col, newValue);
}}
onBlur={() => {
setControlShow(false);
setChangeContent(false);
}}
/>
<a className="position-absolute z-1 top-0 end-0 mt-1 me-1 d-none" href="#" tabIndex={-1} onClick={(e: React.MouseEvent) => {
e.preventDefault();
setControlShow(false);
setChangeContent(false);
}}>
<svg width="20px" height="20px" viewBox="0 0 1024 1024" fill="#f00"><path d="M512 897.6c-108 0-209.6-42.4-285.6-118.4-76-76-118.4-177.6-118.4-285.6 0-108 42.4-209.6 118.4-285.6 76-76 177.6-118.4 285.6-118.4 108 0 209.6 42.4 285.6 118.4 157.6 157.6 157.6 413.6 0 571.2-76 76-177.6 118.4-285.6 118.4z m0-760c-95.2 0-184.8 36.8-252 104-67.2 67.2-104 156.8-104 252s36.8 184.8 104 252c67.2 67.2 156.8 104 252 104 95.2 0 184.8-36.8 252-104 139.2-139.2 139.2-364.8 0-504-67.2-67.2-156.8-104-252-104z" fill="" /><path d="M707.872 329.392L348.096 689.16l-31.68-31.68 359.776-359.768z" fill="" /><path d="M328 340.8l32-31.2 348 348-32 32z" fill="" /></svg>
</a>
</div>
</>: null}
</>
);
}
const EditableCellTime = (props: any) => {
const {
itemData,
rowIndex,
colIndex,
defaultValue,
onChange,
onConfirm
} = props;
const popupRef = useRef<any>();
const inputRef = useRef<any>();
const inputWrapperRef = useRef<HTMLDivElement>(null);
const [defaultVurVal, setDefaultVurVal] = useState<string>(defaultValue);
const curVal = useRef<string>(defaultValue);
return (
<>
<div
ref={inputWrapperRef}
className={`position-absolute z-1 top-0 start-0`}
style={{ width: '200px' }}
>
<Date
delimiter="-"
showToolsWhenHover
wrapperClassName="position-relative app-data-editable"
popupRef={popupRef}
contentRef={inputRef}
value={defaultVurVal === '-' ? '' : defaultVurVal}
placeholder="Edit"
data-uid={`${rowIndex}`}
data-col={colIndex}
data-use={JSON.stringify(itemData)}
type="datetime-local"
localization="zh_CN"
style={{border: 'none', background: 'transparent', textAlign: 'center', fontSize: '0.75rem'}}
onChangeSeconds={(dateRes: any) => {
// close popup
if (popupRef.current) popupRef.current.close();
}}
onChange={(input: HTMLInputElement, dateRes: any, isValidDate: boolean) => {
const _res = dateRes !== null && typeof dateRes !== 'string' ? dateRes.res : dateRes;
curVal.current = _res;
onChange?.(input.dataset.row, input.dataset.col, _res);
}}
onBlur={(el: any) => {
if (typeof el.dataset.use !== 'undefined' && el.dataset.use !== '') {
const _itemData = JSON.parse(el.dataset.use);
onConfirm?.(_itemData, curVal.current);
}
}}
/>
</div>
</>
);
}
const Main = (props: any) => {
const {
otherdeps
} = props;
const [tableData, setTableData] = useState<any[]>([]);
useEffect(() => {
// test async
setTableData([
{money: "$55.134", name: "David Lin", no: "3453434", date1: "2012-09-25T12:10:46+00:00", date2: "May 22, 2003"},
{money: "$255.12", name: "Co Cheey", no: "-2324.343", date1: "2013-09-10T12:10:46+00:00", date2: "September 13, 2013"},
{money: "$21.134", name: "Foristin", no: "-34789.34", date1: "2018-09-24T12:10:46+00:00", date2: "January 2, 2019"},
{money: "$3454.134", name: "Alice", no: "+224.5", date1: "2011-09-21T12:10:46+00:00", date2: "December 1, 2018"},
{money: "$224.0", name: "Wooli", no: "+33.6", date1: "2011-02-26T12:10:46+00:00", date2: "July 22, 2017"},
{money: "$356.2", name: "Spiter Low", no: "278.23487", date1: "2019-01-01T12:10:46+00:00", date2: "July 28, 2017"},
]);
}, [otherdeps]); // The Main component will be re-rendered due to `otherdeps`
return (
<>
<Table
tableClassName="table table-bordered"
data={tableData}
>
<TableHead>
<TableRow>
<TableCell scope="col" nowrap>#</TableCell>
<TableCell scope="col" nowrap>Money</TableCell>
<TableCell scope="col" nowrap style={{ width: '200px' }}>Name</TableCell>
<TableCell scope="col" nowrap>No.</TableCell>
<TableCell scope="col" nowrap style={{ width: '200px' }}>Date1</TableCell>
<TableCell scope="col" nowrap>Date2</TableCell>
</TableRow>
</TableHead>
<TableBody>
{tableData.map((item: any, index: number) => {
return <TableRow
key={`row-${index}`}
data-key={`row-${index}`}
itemData={item}
>
<TableCell scope="row">{index}</TableCell>
<TableCell>{item.money}</TableCell>
<TableCell>
<EditableCellInput
rowIndex={index}
colIndex={2}
defaultValue={item.name}
onChange={(uid: string, col: number, value: string) => {
console.log(uid, col, value);
}}
/>
</TableCell>
<TableCell>{item.no}</TableCell>
<TableCell>
<EditableCellTime
rowIndex={index}
colIndex={4}
itemData={item}
defaultValue={item.date1.replace('T', ' ')}
onConfirm={(data: any, newtime: string) => {
console.log(data, newtime);
}}
/>
</TableCell>
<TableCell>{item.date2}</TableCell>
</TableRow>
})}
</TableBody>
</Table>
</>
);
}
export default Main;Navigate a cell <TableCell /> through arrow keys
Use the arrow keys of your keyboard to locate the cells.
To interact with data is required using the
dataproperty of<Table />anditemDataproperty of<TableRow />.
It is valid when keyboardFocusable is "true". You can set more properties, such as: onCellKeyPressed and onCellPressEnter.
| # | Money | Name | No. | Date1 | Date2 |
|---|
Show Code
import React, { useRef, useState, useEffect } from "react";
import {
Table,
TableBody,
TableCell,
TableHead,
TableRow,
} from 'funda-ui/Table';
// component styles
import 'funda-ui/Table/index.css';
export default () => {
const [tableData, setTableData] = useState<any[]>([]);
useEffect(() => {
// test async
setTableData([
{money: "$55.134", name: "David Lin", no: "3453434", date1: "2012-09-25T12:10:46+00:00", date2: "May 22, 2003"},
{money: "$255.12", name: "Co Cheey", no: "-2324.343", date1: "2013-09-10T12:10:46+00:00", date2: "September 13, 2013"},
{money: "$21.134", name: "Foristin", no: "-34789.34", date1: "2018-09-24T12:10:46+00:00", date2: "January 2, 2019"},
{money: "$3454.134", name: "Alice", no: "+224.5", date1: "2011-09-21T12:10:46+00:00", date2: "December 1, 2018"},
{money: "$224.0", name: "Wooli", no: "+33.6", date1: "2011-02-26T12:10:46+00:00", date2: "July 22, 2017"},
{money: "$356.2", name: "Spiter Low", no: "278.23487", date1: "2019-01-01T12:10:46+00:00", date2: "July 28, 2017"},
]);
}, []);
return (
<>
<Table
tableClassName="table table-bordered"
data={tableData}
keyboardFocusable
onCellKeyPressed={(
classname: string,
elem: HTMLTableCellElement,
event: React.KeyboardEvent<Element>,
isLeftEdge: boolean,
isRightEdge: boolean,
isTopEdge: boolean,
isBottomEdge: boolean
) => {
console.log(classname, elem, event);
// You can have a scrollable div locate visible elements in real time as you move in the direction of the keyboard
/*
const key = event.code;
const updateScrollPos = () => {
if (scrollDivRef.current === null) return;
// Scroll to ".cell-focus"
setTimeout(() => {
const cell = scrollDivRef.current.querySelector('.cell-focus');
if (cell) {
(cell as HTMLElement).scrollIntoView({ block: 'nearest', behavior: 'auto' });
}
}, 0);
};
switch (key) {
case 'ArrowUp':
case 'Numpad8':
updateScrollPos();
break;
case 'ArrowDown':
case 'Numpad2':
updateScrollPos();
break;
}
*/
if (isLeftEdge) {
console.log('isLeftEdge: ', isLeftEdge);
}
if (isRightEdge) {
console.log('isRightEdge: ', isRightEdge);
}
if (isTopEdge) {
console.log('isTopEdge: ', isTopEdge);
}
if (isBottomEdge) {
console.log('isBottomEdge: ', isBottomEdge);
}
}}
onCellPressEnter={(classname: string, elem: HTMLTableCellElement, event: React.KeyboardEvent<Element>) => {
console.log(classname, elem, event);
}}
>
<TableHead>
<TableRow>
<TableCell scope="col" nowrap>#</TableCell>
<TableCell scope="col" nowrap>Money</TableCell>
<TableCell scope="col" nowrap>Name</TableCell>
<TableCell scope="col" nowrap>No.</TableCell>
<TableCell scope="col" nowrap>Date1</TableCell>
<TableCell scope="col" nowrap>Date2</TableCell>
</TableRow>
</TableHead>
<TableBody>
{tableData.map((item: any, index: number) => {
return <TableRow
key={`row-${index}`}
data-key={`row-${index}`}
itemData={item}
>
<TableCell scope="row">{index}</TableCell>
<TableCell>{item.money}</TableCell>
<TableCell>{item.name}</TableCell>
<TableCell>{item.no}</TableCell>
<TableCell>{item.date1}</TableCell>
<TableCell>{item.date2}</TableCell>
</TableRow>
})}
</TableBody>
</Table>
</>
);
}Determine whether the table has been rendered
| # | Money | Name | No. | Date1 | Date2 |
|---|
Show Code
import React, { useRef, useState, useEffect, Suspense } from "react";
import {
Table,
TableBody,
TableCell,
TableHead,
TableRow,
} from 'funda-ui/Table';
// component styles
import 'funda-ui/Table/index.css';
const MyTable = () => {
const [tableData, setTableData] = useState<any[]>([]);
useEffect(() => {
// test async
setTableData([
{money: "$55.134", name: "David Lin", no: "3453434", date1: "2012-09-25T12:10:46+00:00", date2: "May 22, 2003"},
{money: "$255.12", name: "Co Cheey", no: "-2324.343", date1: "2013-09-10T12:10:46+00:00", date2: "September 13, 2013"},
{money: "$21.134", name: "Foristin", no: "-34789.34", date1: "2018-09-24T12:10:46+00:00", date2: "January 2, 2019"},
{money: "$3454.134", name: "Alice", no: "+224.5", date1: "2011-09-21T12:10:46+00:00", date2: "December 1, 2018"},
{money: "$224.0", name: "Wooli", no: "+33.6", date1: "2011-02-26T12:10:46+00:00", date2: "July 22, 2017"},
{money: "$356.2", name: "Spiter Low", no: "278.23487", date1: "2019-01-01T12:10:46+00:00", date2: "July 28, 2017"},
]);
}, []);
return (
<>
<Table
tableClassName="table table-bordered"
data={tableData}
>
<TableHead>
<TableRow>
<TableCell scope="col" nowrap>#</TableCell>
<TableCell scope="col" nowrap>Money</TableCell>
<TableCell scope="col" nowrap>Name</TableCell>
<TableCell scope="col" nowrap>No.</TableCell>
<TableCell scope="col" nowrap>Date1</TableCell>
<TableCell scope="col" nowrap>Date2</TableCell>
</TableRow>
</TableHead>
<TableBody>
{tableData.map((item: any, index: number) => {
return <TableRow
key={`row-${index}`}
data-key={`row-${index}`}
itemData={item}
>
<TableCell scope="row">{index}</TableCell>
<TableCell>{item.money}</TableCell>
<TableCell>{item.name}</TableCell>
<TableCell>{item.no}</TableCell>
<TableCell>{item.date1}</TableCell>
<TableCell>{item.date2}</TableCell>
</TableRow>
})}
</TableBody>
</Table>
</>
);
}
export default () => {
return (
<>
<Suspense fallback={<>Loading...</>}>
<MyTable />
</Suspense>
</>
);
}Set the value of a <ToggleSelection /> (Radio control)
Click on the current row to activate the radio of the current row.
| # | Name | Friend | Condition | Operations |
|---|
Show Code
import React, { useRef, useState, useEffect } from "react";
import {
Table,
TableBody,
TableCell,
TableHead,
TableRow,
// utils
ToggleSelection,
} from 'funda-ui/Table';
// component styles
import 'funda-ui/Table/index.css';
export default () => {
const [tableData, setTableData] = useState<any[]>([]);
//
const tableCheckRef = useRef<Map<string, HTMLTableElement>>(new Map());
const [selectedRowData, setSelectedRowData] = useState<any[] | null>(null);
useEffect(() => {
// test async
setTableData([
{ name: 'David', friend: 'Jone', condition: 'GOOD' },
{ name: 'Chuckie', friend: 'Jone', condition: 'BAD' },
{ name: 'Smith Jone', friend: 'Lomi', condition: 'GOOD' },
{ name: 'Frank', friend: 'Alice', condition: 'PERFECT' },
]);
}, []);
return (
<>
<Table
rowSelectable
tableClassName="table"
data={tableData}
dataSelected={[]}
onChangeRowSelect={(fetchData) => {
setSelectedRowData(fetchData);
}}
>
<TableHead>
<TableRow>
<TableCell scope="col" nowrap style={{width: '25px'}}></TableCell>
<TableCell scope="col" nowrap>#</TableCell>
<TableCell scope="col" nowrap>Name</TableCell>
<TableCell scope="col" nowrap>Friend</TableCell>
<TableCell scope="col" nowrap>Condition</TableCell>
<TableCell scope="col" nowrap>Operations</TableCell>
</TableRow>
</TableHead>
<TableBody>
{tableData.map((item, index) => {
return <TableRow
key={`row-${index}`}
data-key={`row-${index}`}
itemData={item}
style={{'cursor': 'pointer'}}
onClick={(e: React.MouseEvent) => {
setSelectedRowData([item]);
// trigger target checkbox
if (tableCheckRef.current !== null) {
const currentCheckbox: any = tableCheckRef.current.get(item.name);
// deselecting all
for (let [key, value] of tableCheckRef.current as any) {
value.set(false);
}
// select current target
currentCheckbox.set(true);
}
}}
>
<TableCell scope="row">
{/** Checkbox */}
<div className="checkbox-indeterminate">
<ToggleSelection
useRadio
row={index}
contentRef={(node: any) => {
if (node) {
tableCheckRef.current.set(item.name, node);
}
}}
/>
</div>
</TableCell>
<TableCell scope="row">{index}</TableCell>
<TableCell>{item.name}</TableCell>
<TableCell>{item.friend}</TableCell>
<TableCell>{item.condition}</TableCell>
<TableCell>
{selectedRowData !== null && selectedRowData[0].name === item.name ? <>
<button tabIndex={-1} type="button" onClick={(e: React.MouseEvent) => {
e.preventDefault();
e.stopPropagation();
}}>Detail</button>
</> : ''}
</TableCell>
</TableRow>
})}
</TableBody>
</Table>
<small>Selected: {selectedRowData && selectedRowData[0].name}</small>
</>
);
}Set the value of a <ToggleSelection /> (Checkbox control)
Click on the current row to activate the checkbox of the current row.
| # | Name | Friend | Condition | Operations |
|---|
Deselecting all | Selecting all
Selected:Show Code
import React, { useRef, useState, useEffect } from "react";
import {
Table,
TableBody,
TableCell,
TableHead,
TableRow,
// utils
ToggleSelection,
} from 'funda-ui/Table';
// component styles
import 'funda-ui/Table/index.css';
export default () => {
const [tableData, setTableData] = useState<any[]>([]);
//
const tableSelectAllRef = useRef<any>(null);
const tableCheckRef = useRef<Map<string, HTMLTableElement>>(new Map());
const [selectedRowData, setSelectedRowData] = useState<any[]>([]);
useEffect(() => {
// test async
setTableData([
{ name: 'David', friend: 'Jone', condition: 'GOOD' },
{ name: 'Chuckie', friend: 'Jone', condition: 'BAD' },
{ name: 'Smith Jone', friend: 'Lomi', condition: 'GOOD' },
{ name: 'Frank', friend: 'Alice', condition: 'PERFECT' },
]);
}, []);
return (
<>
<Table
rowSelectable
tableClassName="table"
data={tableData}
dataSelected={[]}
onChangeRowSelect={(fetchData) => {
setSelectedRowData(fetchData);
}}
>
<TableHead>
<TableRow>
<TableCell scope="col" nowrap style={{width: '25px'}}>
{/** Checkbox */}
<div className="checkbox-indeterminate">
<ToggleSelection row={-1} contentRef={tableSelectAllRef} />
</div>
</TableCell>
<TableCell scope="col" nowrap>#</TableCell>
<TableCell scope="col" nowrap>Name</TableCell>
<TableCell scope="col" nowrap>Friend</TableCell>
<TableCell scope="col" nowrap>Condition</TableCell>
<TableCell scope="col" nowrap>Operations</TableCell>
</TableRow>
</TableHead>
<TableBody>
{tableData.map((item, index) => {
return <TableRow
key={`row-${index}`}
data-key={`row-${index}`}
itemData={item}
style={{'cursor': 'pointer'}}
onClick={(e) => {
setSelectedRowData((prevState: any[]) => {
const exists = prevState.some(obj => obj.name === item.name);
let newState;
if (exists) {
newState = prevState.filter(obj => obj.name !== item.name);
} else {
const merged = [...prevState, item];
newState = Array.from(new Map(merged.map(obj => [obj.name, obj])).values());
}
// Initialize indeterminate status of all checkboxes
setTimeout(() => {
if (tableSelectAllRef.current) {
if (newState.length > 0 || newState.length < tableData.length) tableSelectAllRef.current.indeterminate(true);
if (newState.length === 0 || newState.length === tableData.length) tableSelectAllRef.current.indeterminate(false);
if (newState.length === 0) tableSelectAllRef.current.setSelectAll(false);
if (newState.length === tableData.length) tableSelectAllRef.current.setSelectAll(true);
}
}, 0);
return newState;
});
// trigger target checkbox
if (tableCheckRef.current !== null) {
const currentCheckbox = tableCheckRef.current.get(item.name);
if (currentCheckbox) {
currentCheckbox.set(!currentCheckbox.control().checked);
}
}
}}
>
<TableCell scope="row">
{/** Checkbox */}
<div className="checkbox-indeterminate">
<ToggleSelection
row={index}
contentRef={(node: any) => {
if (node) {
tableCheckRef.current.set(item.name, node);
}
}}
onChange={(e: React.MouseEvent, val: boolean, fetchData: any[]) => {
// Initialize indeterminate status of all checkboxes
if (tableSelectAllRef.current) {
if (fetchData.length > 0 || fetchData.length < tableData.length) tableSelectAllRef.current.indeterminate(true);
if (fetchData.length === 0 || fetchData.length === tableData.length) tableSelectAllRef.current.indeterminate(false);
if (fetchData.length === 0) tableSelectAllRef.current.setSelectAll(false);
if (fetchData.length === tableData.length) tableSelectAllRef.current.setSelectAll(true);
}
}}
/>
</div>
</TableCell>
<TableCell scope="row">{index}</TableCell>
<TableCell>{item.name}</TableCell>
<TableCell>{item.friend}</TableCell>
<TableCell>{item.condition}</TableCell>
<TableCell>
{selectedRowData !== null && selectedRowData.map((v: any) => v.name).includes(item.name) ? <>
<button tabIndex={-1} type="button" onClick={(e: React.MouseEvent) => {
e.preventDefault();
e.stopPropagation();
}}>Detail</button>
</> : ''}
</TableCell>
</TableRow>
})}
</TableBody>
</Table>
<p>
<a href="#" onClick={(e) => {
e.preventDefault();
setSelectedRowData([]);
// trigger target checkbox
if (tableCheckRef.current !== null) {
for (let [key, value] of tableCheckRef.current as any) {
value.set(false);
}
}
if (tableSelectAllRef.current) {
tableSelectAllRef.current.indeterminate(false);
tableSelectAllRef.current.setSelectAll(false);
}
}}>Deselecting all</a>
|
<a href="#" onClick={(e) => {
e.preventDefault();
setSelectedRowData(tableData);
// trigger target checkbox
if (tableCheckRef.current !== null) {
for (let [key, value] of tableCheckRef.current as any) {
value.set(true);
}
}
if (tableSelectAllRef.current) {
tableSelectAllRef.current.indeterminate(false);
tableSelectAllRef.current.setSelectAll(true);
}
}}>Selecting all</a>
</p>
<small>Selected: {selectedRowData && selectedRowData.map((v: any) => v.name).join(',')}</small>
</>
);
}❤️ FAQ
State changes in the page, causing other <Table /> components to re-render and value to reset.
Solution:
The
dataproperty of the controlled component must be stable references so that the initial values are not reset due to re-rendering caused by changes in the state (usinguseState()) of the page.
Example:
👍 Good
Use useMemo() to return the entire component
| # | Name | Friend | Condition |
|---|
Show Code
import React, { useRef, useState, useEffect, useMemo } from "react";
import {
Table,
TableBody,
TableCell,
TableHead,
TableRow,
// utils
ToggleSelection,
} from 'funda-ui/Table';
// component styles
import 'funda-ui/Table/index.css';
// DO NOT move `useMemo` to component
function MemoTable(props: any) {
const {data} = props;
const tableSelectAllRef = useRef<any>(null);
return useMemo(() => {
return <Table
rowSelectable
tableClassName="table"
data={data}
// dataSelected={[1,3]}
onChangeRowSelect={(fetchData: any[]) => {
console.log(fetchData);
}}
>
<TableHead>
<TableRow>
<TableCell scope="col" nowrap style={{width: '25px'}}>
{/** Checkbox */}
<div className="checkbox-indeterminate">
<ToggleSelection row={-1} contentRef={tableSelectAllRef} />
</div>
</TableCell>
<TableCell scope="col" nowrap>#</TableCell>
<TableCell scope="col" nowrap>Name</TableCell>
<TableCell scope="col" nowrap>Friend</TableCell>
<TableCell scope="col" nowrap>Condition</TableCell>
</TableRow>
</TableHead>
<TableBody>
{data.map((item: any, index: number) => {
return <TableRow
key={`row-${index}`}
data-key={`row-${index}`}
itemData={item}
>
<TableCell scope="row">
{/** Checkbox */}
<div className="checkbox-indeterminate">
<ToggleSelection
row={index}
onChange={(e: React.MouseEvent, val: boolean, fetchData: any[]) => {
// Initialize indeterminate status of all checkboxes
if (tableSelectAllRef.current) {
if (fetchData.length > 0 || fetchData.length < data.length) tableSelectAllRef.current.indeterminate(true);
if (fetchData.length === 0 || fetchData.length === data.length) tableSelectAllRef.current.indeterminate(false);
if (fetchData.length === 0) tableSelectAllRef.current.setSelectAll(false);
if (fetchData.length === data.length) tableSelectAllRef.current.setSelectAll(true);
}
}}
/>
</div>
</TableCell>
<TableCell scope="row">{index}</TableCell>
<TableCell>{item.name}</TableCell>
<TableCell>{item.friend}</TableCell>
<TableCell>{item.condition}</TableCell>
</TableRow>
})}
</TableBody>
</Table>;
}, [data]);
}
export default () => {
const [tableData, setTableData] = useState<any[]>([]);
useEffect(() => {
// test async
setTableData([
{ name: 'David', friend: 'Jone', condition: 'GOOD' },
{ name: 'Chuckie', friend: 'Jone', condition: 'BAD' },
{ name: 'Smith Jone', friend: 'Lomi', condition: 'GOOD' },
{ name: 'Frank', friend: 'Alice', condition: 'PERFECT' },
]);
}, []);
return (
<>
<MemoTable
data={tableData}
/>
</>
);
}❤️ API
❤️ You could specify all remaining properties defined and all synthetic events from React on all components listed below. such as
tabIndex,style,id,data-xxx,onClick,onMouseEnter,onMouseLeave, and so on.
<Table /><TableBody /><TableHead /><TableFoot /><TableRow /><TableColgroup /><TableCaption /><TableFilter /><ToggleSelection /><DragHandleSprite /><SortSprite />
Table
import { Table } from 'funda-ui/Table';| Property | Type | Default | Description | Required |
|---|---|---|---|---|
ref | React.ForwardedRef | - | It is the return element of this component. | - |
contentRef | React.ForwardedRef | - | It exposes the following methods of the component:
| - |
wrapperClassName | string | mb-3 position-relative | The class name of the table wrapper. | - |
tableClassName | string | table | The class name of the table wrapper. | - |
data | Array | - | Array of objects, where each object represents one item - row in table. such as [{name:'David',friend:'Jone',condition:'GOOD'},{name:'Chuckie',friend:'Jone',condition:'BAD'}] Enable it to enable some special features | - |
dataSelected | Array | - | Array of numbers, Selected data when rowSelectable is enabled. It's an array of indexed numbers, such as [1,3] It is valid when | - |
rowDraggable | boolean | false | Indicates whether the per row can be dragged. The | - |
rowSelectable | boolean | false | Use of Checkboxes and clickable rows for selection. The | - |
colSortable | boolean | false | Support sort a column (or columns) when the table is built. The components are used in each column of the head. The
| - |
keyboardFocusable | boolean | false | Use the arrow keys on your keyboard to focus on each cell. The | - |
filterFields | Array | - | Fields used for filtering. such as ['name', 'friend'] The | - |
bordered | boolean | false | Adds borders on all sides of the table and cells | - |
colGroup | boolean | false | Set the background color of the multiple columns with the <colgroup> and <col> tags | - |
cellAutoWidth | boolean | false | Width does not expand automatically, each cell uses a custom minimum width. If the content is exceeded, there will be a horizontal scrollbar on the table. And if this attribute exists, the <TableCell /> in the <TableHead /> | - |
responsive | boolean | true | For horizontally scrolling tables on the wrapper. | - |
enhancedResponsive | boolean | false | Create enhanced responsive tables up to a particular breakpoint. Valid when the device width is less than or equal to 768px. | - |
enhancedResponsiveWithScrollBar | boolean | false | Create enhanced responsive tables up to a particular breakpoint. This property allows scroll bars to be created automatically in the table with floating header. Valid when the device width is less than or equal to 768px. | - |
onChangeFilter | function | - | Call a function when the value changed. It returns one callback value which is the fetched data (Array). | - |
onChangeRowSelect | function | - | Call a function when the selection box for the current row is changed. It returns one callback value which is the fetched data (Array). It is valid when | - |
onRowDrag | function | - | As each row is dragged, it returns two functions. dragStart, dragEnd, they represent the callback events of drag start and drag end respectively. For example: onRowDrag={(dragStart,dragEnd)=>{if(dragStart!==null)dragStart((el:HTMLTableRowElement,order:number[],data:any[])=>{console.log('dragStart: ',el,order,data);});if(dragEnd!==null)dragEnd((el:HTMLTableRowElement,order:number[],data:any[])=>{console.log('dragEnd: ',el,order,data);});}}. It is valid when | - |
onColSort | function | - | Call a function when the column sorting succeeds. It returns one callback value which is the fetched data (Array). It is valid when | - |
onCellKeyPressed | function | - | It fires when use keyboard arrow keys. It returns seven callback values.
It is valid when | - |
onCellPressEnter | function | - | The callback function that is triggered when Enter key is pressed. It returns three callback values.
| - |
👉🏼 JSON configuration properties of the data => It can be any array of objects in JSON format.
Table Body
import { TableBody } from 'funda-ui/Table';| Property | Type | Default | Description | Required |
|---|---|---|---|---|
ref | React.ForwardedRef | - | It is the return element of this component. | - |
className | string | - | The class name of the table body. | - |
Table Cell
import { TableCell } from 'funda-ui/Table';| Property | Type | Default | Description | Required |
|---|---|---|---|---|
ref | React.ForwardedRef | - | It is the return element of this component. | - |
className | string | - | The class name of the table cell as <td> or <th>. | - |
active | boolean | false | Whether to activate the current row. | - |
activeClassName | string | active | The class name of actived. | - |
colSpan | number | 1 | The value represents the number of columns to span. | - |
nowrap | boolean | false | Sequences of whitespace will collapse into a single whitespace. Text will never wrap to the next line. | - |
scope | col | row | colgroup | rowgroup | - | The scope attribute specifies whether a header cell is a header for a column, row, or group of columns or rows. | - |
Table Head
import { TableHead } from 'funda-ui/Table';| Property | Type | Default | Description | Required |
|---|---|---|---|---|
ref | React.ForwardedRef | - | It is the return element of this component. | - |
className | string | - | The class name of the table head. | - |
Table Foot
import { TableFoot } from 'funda-ui/Table';| Property | Type | Default | Description | Required |
|---|---|---|---|---|
ref | React.ForwardedRef | - | It is the return element of this component. | - |
className | string | - | The class name of the table foot. | - |
Table Row
import { TableRow } from 'funda-ui/Table';| Property | Type | Default | Description | Required |
|---|---|---|---|---|
ref | React.ForwardedRef | - | It is the return element of this component. | - |
className | string | - | The class name of the table row as <tr>. | - |
active | boolean | false | Whether to activate the current row. | - |
activeClassName | string | active | The class name of actived. | - |
itemData | JSON Object | - | Data for each row. such as {name:'David',friend:'Jone',condition:'GOOD'} | - |
Table Colgroup
import { TableColgroup } from 'funda-ui/Table';| Property | Type | Default | Description | Required |
|---|---|---|---|---|
ref | React.ForwardedRef | - | It is the return element of this component. | - |
className | string | - | The class name of the table colgroup. | - |
length | number | - | Specifies how many elements a group has. | - |
captionSide | top | bottom | top | This property puts the content of a table's <caption> on the specified side. | - |
Table Caption
import { TableCaption } from 'funda-ui/Table';| Property | Type | Default | Description | Required |
|---|---|---|---|---|
ref | React.ForwardedRef | - | It is the return element of this component. | - |
className | string | - | The class name of the table caption. | - |
Filter Input
import { TableFilter } from 'funda-ui/Table';| Property | Type | Default | Description | Required |
|---|---|---|---|---|
ref | React.ForwardedRef | - | It is the return element of this component. | - |
className | string | - | The class name of the filter input control. | - |
placeholder | string | - | The placeholder of the filter input control. | - |
label | ReactNode | null | Label for filter input control. | - |
onChange | function | - | Call a function when the value of an HTML element is changed. It returns two callback values.
| - |
Toggle Selection
It will be presented in the form of a checkbox.
import { ToggleSelection } from 'funda-ui/Table';| Property | Type | Default | Description | Required |
|---|---|---|---|---|
ref | React.ForwardedRef | - | It is the return element of this component. | - |
contentRef | React.ForwardedRef | - | It exposes the following methods:
DO NOT USE it in the | - |
row | number | - | For the current row, set -1 if it is the head area. | ✅ |
className | string | - | The class name of the table caption. | - |
checked | boolean | false | Is it selected. | - |
useRadio | boolean | false | Use radio instead of Checkbox. | - |
indeterminate | boolean | false | Set a checkbox to indeterminate state. | - |
value | string | - | Set a default value for this control. If unchecked, it will pass an empty value | ✅ |
name | string | - | Name is not deprecated when used with form fields. | - |
disabled | boolean | false | Whether it is disabled | - |
onChange | function | - | Call a function when the value of an HTML element is changed. It returns three callback values.
| - |
Drag Handle Sprite
import { DragHandleSprite } from 'funda-ui/Table';| Property | Type | Default | Description | Required |
|---|---|---|---|---|
ref | React.ForwardedRef | - | It is the return element of this component. | - |
className | string | drag-trigger | The class name of the filter input control. | - |
icon | ReactNode | <svg width="1em" height="1em" viewBox="0 0 24 24" fill="none"><g><path d="M18 14C17.4477 14 17 14.4477 17 15C17 15.5523 17.4477 16 18 16C18.5523 16 19 15.5523 19 15C19 14.4477 18.5523 14 18 14Z" stroke="#000000" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" /><path d="M12 14C11.4477 14 11 14.4477 11 15C11 15.5523 11.4477 16 12 16C12.5523 16 13 15.5523 13 15C13 14.4477 12.5523 14 12 14Z" stroke="#000000" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" /><path d="M6 14C5.44772 14 5 14.4477 5 15C5 15.5523 5.44772 16 6 16C6.55228 16 7 15.5523 7 15C7 14.4477 6.55228 14 6 14Z" stroke="#000000" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" /><path d="M18 8C17.4477 8 17 8.44772 17 9C17 9.55228 17.4477 10 18 10C18.5523 10 19 9.55228 19 9C19 8.44772 18.5523 8 18 8Z" stroke="#000000" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" /><path d="M12 8C11.4477 8 11 8.44772 11 9C11 9.55228 11.4477 10 12 10C12.5523 10 13 9.55228 13 9C13 8.44772 12.5523 8 12 8Z" stroke="#000000" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" /><path d="M6 8C5.44772 8 5 8.44772 5 9C5 9.55228 5.44772 10 6 10C6.55228 10 7 9.55228 7 9C7 8.44772 6.55228 8 6 8Z" stroke="#000000" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" /></g></svg> | Specify an icon | - |
Sort Sprite
import { SortSprite } from 'funda-ui/Table';| Property | Type | Default | Description | Required |
|---|---|---|---|---|
ref | React.ForwardedRef | - | It is the return element of this component. | - |
className | string | sort-trigger | The class name of the filter input control. | - |
fieldType | text | number | date | text | The type of field that is sorted, which ensures the accuracy of sorting. | ✅ |
isReverse | boolean | false | Whether the order is reversed | - |
icon | ReactNode | <svg width="1em" height="1em" viewBox="0 0 18 18"><g stroke="none" strokeWidth="1" fill="none" fillRule="evenodd"><path d="M9.5,3 L13,8 L6,8 L9.5,3 L9.5,3 Z M6,11 L13,11 L9.5,16 L6,11 L6,11 Z" id="path" fill="#000000"></path></g></svg> | Specify an icon | - |
sortBy | (handleProcess: Function, filterType: string, inverse: boolean) => (a: Element, b: Element) => number | - | Custom sort function generator. This function receives three arguments:
(a, b) => number. If not provided, a default sort logic is used. | - |