Table (Synthetic)

General

a) Basic


#Title 1Title 2Title 3
1DavidJoneGood
2ChuckieJoneBAD
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 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>
                    </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>BAD</TableCell>
                    </TableRow>
                    <TableRow>
                        <TableCell scope="row">3</TableCell>
                        <TableCell colSpan={2}>
                            Hi There
                        </TableCell>
                        <TableCell>Cool</TableCell>
                    </TableRow>
                </TableBody>
            </Table>
         
        </>
    );
}

b) Cell Auto Width


#Title 1Title 2Title 3
1DavidJoneGood
2ChuckieJonePictures 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 1Title 2Title 3
0DavidJoneGOOD
1ChuckieJoneBAD
2Smith JoneLomiPictures are worth a thousand words, right? So Tom x 1,000.
3FrankAlicePERFECT
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 1Title 2Title 3
0DavidJoneGOOD
1ChuckieJoneBAD
2Smith JoneLomiPictures are worth a thousand words, right? So Tom x 1,000.
3FrankAlicePERFECT
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 1Title 2Title 3
1DavidJoneGood
2ChuckieJonePictures 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.

Holy Grail Layout (3 columns)


#Title1Title2Title3Title4Title5Title6Title7Title8Title9Title10Title11Title12Title13Title14Title15Title16Title17Title18Title19Title20Title21Title22Title23Title24Title25Title26Title27Title28Title29Title30Title31Title32Title33Title34Title35Title36Title37Title38Title39Title40Title41Title42Title43Title44Title45Title46Title47Title48Title49
No.03535076592049898485888071162838428776294690712326811467118598381424992983567553699564425681962813
No.16560431568455843400449242528381327588182080466129672325362666615124018939336649246332523701328
No.22985217068275874951321578127898388162586263163808311408427213323447073704557055928493952421026
No.37993275125713361443293804095424125372419935677238153116692483140874959849531134682609465919
No.4473832723558941998415615925711922510452855141325355475059298618973551633484579736639725245495262
No.53627218592407577891654454359133505619136752808130361652736990237597293754529111835131836640464
No.62650339395215917857435922113747661730486212828694881542242214559244802249525296366527197694599
No.743415612483675496275185352435703893363173156296161933011834303112416787234114781597128229764
No.842574333527258691713371518787764374330945730168683345421972981295111518756749239119711244905942
No.9311734384081742847661747514230588483938464476080968428170699762225669152662653582776723698
No.102622483744672112207615992224569765172597676448491497411083892451696939578265096991421518404848
No.113183702686409383313269488948463611076852431831331462746637768168072317655484570597260183681436555
No.121768719646879149066530227884761831128193580442616754240805843754129705371949684088354939913099
No.132862615565773270229929724386799648094511649772360709776971589684934428992037927843428949144
No.146184956513446483581664058762956946616436344660297273451477858617927385964763178583367668268381
No.159298708666826967695613573689895325932496166531442864352485261464356826623699029416514654022529541
No.16241042483569136138663666815531953197843772091834251377243178242592481163668708363837358927030
No.176674374753514057315171623679634031858799251795237681974292920827308085293818452229867256262715
No.18559462864718129032734508949422527523557978166222425947645972212295325080628723519318587360
No.1958518320636466936146634847195778152578852592366445145359463559891168319672194752959085471345
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;
            top: 0;
        }
 
        tbody > tr > th {
            position: sticky;
            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)


#Title1Title2Title3Title4Title5Title6Title7Title8Title9Title10Title11Title12Title13Title14Title15Title16Title17Title18Title19Title20Title21Title22Title23Title24Title25Title26Title27Title28Title29Title30Title31Title32Title33Title34Title35Title36Title37Title38Title39Title40Title41Title42Title43Title44Title45Title46Title47Title48Title49
No.03535076592049898485888071162838428776294690712326811467118598381424992983567553699564425681962813
No.16560431568455843400449242528381327588182080466129672325362666615124018939336649246332523701328
No.22985217068275874951321578127898388162586263163808311408427213323447073704557055928493952421026
No.37993275125713361443293804095424125372419935677238153116692483140874959849531134682609465919
No.4473832723558941998415615925711922510452855141325355475059298618973551633484579736639725245495262
No.53627218592407577891654454359133505619136752808130361652736990237597293754529111835131836640464
No.62650339395215917857435922113747661730486212828694881542242214559244802249525296366527197694599
No.743415612483675496275185352435703893363173156296161933011834303112416787234114781597128229764
No.842574333527258691713371518787764374330945730168683345421972981295111518756749239119711244905942
No.9311734384081742847661747514230588483938464476080968428170699762225669152662653582776723698
No.102622483744672112207615992224569765172597676448491497411083892451696939578265096991421518404848
No.113183702686409383313269488948463611076852431831331462746637768168072317655484570597260183681436555
No.121768719646879149066530227884761831128193580442616754240805843754129705371949684088354939913099
No.132862615565773270229929724386799648094511649772360709776971589684934428992037927843428949144
No.146184956513446483581664058762956946616436344660297273451477858617927385964763178583367668268381
No.159298708666826967695613573689895325932496166531442864352485261464356826623699029416514654022529541
No.16241042483569136138663666815531953197843772091834251377243178242592481163668708363837358927030
No.176674374753514057315171623679634031858799251795237681974292920827308085293818452229867256262715
No.18559462864718129032734508949422527523557978166222425947645972212295325080628723519318587360
No.1958518320636466936146634847195778152578852592366445145359463559891168319672194752959085471345
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;
            top: 0;
        }
 
        tbody > tr > th {
            position: sticky;
            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


#NameFriendCondition
0DavidJoneGOOD
1ChuckieJoneBAD
2Smith JoneLomiPictures are worth a thousand words, right? So Tom x 1,000.
3FrankAlicePERFECT
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 data property of <Table /> and itemData property of <TableRow />.

It is valid when filterFields exists. You can set more properties, such as: onChangeFilter.


#NameFriendCondition
0DavidJoneGOOD
1ChuckieJoneBAD
2Smith JoneLomiPictures are worth a thousand words, right? So Tom x 1,000.
3FrankAlicePERFECT
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 data property of <Table /> and itemData property of <TableRow />.

It is valid when rowSelectable is "true". You can set more properties, such as: onChangeRowSelect, dataSelected.

a) Normal


#NameFriendCondition
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} 
                                        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


#NameFriendCondition
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
#NameFriendCondition
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>   
       
 
        </>
    );
}

Drag and Drop Sort Rows

To interact with data is required using the data property of <Table /> and itemData property of <TableRow />.

It is valid when rowDraggable exists. You can set more properties, such as: onRowDrag.


#NameFriendCondition
0DavidJoneGOOD
1ChuckieJoneBAD
2Smith JoneLomiPictures are worth a thousand words, right? So Tom x 1,000.
3FrankAlicePERFECT
[]
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 data property of <Table /> and itemData property of <TableRow />.

It is valid when colSortable exists. You can set more properties, such as: onColSort.


#Money Name No. Date1 Date2
0$55.134David Lin34534342012-09-25T12:10:46+00:00May 22, 2003
1$255.12Co Cheey-2324.3432013-09-10T12:10:46+00:00September 13, 2013
2$21.134Foristin-34789.342018-09-24T12:10:46+00:00January 2, 2019
3$3454.134Alice+224.52011-09-21T12:10:46+00:00December 1, 2018
4$224.0Wooli+33.62011-02-26T12:10:46+00:00July 22, 2017
5$356.2Spiter Low278.234872019-01-01T12:10:46+00:00July 28, 2017
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: "$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"},
];
 
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" /></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>
 
 
        </>
    );
}

Safe Asynchronous Example

When a useState() in a child component changes state, it will cause the entire parent component to re-render.

At this time, we need to use useMemo() to wrap this subcomponent to avoid problems caused when the child component triggers a method of useState() of the parent component.


#NameFriendCondition
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} 
            />
 
        </>
    );
}

Table Cell Editable


#MoneyNameNo.Date1Date2
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 data property of <Table /> and itemData property of <TableRow />.

It is valid when keyboardFocusable is "true". You can set more properties, such as: onCellKeyPressed.


#MoneyNameNo.Date1Date2
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: KeyboardEvent) => {
                    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


#MoneyNameNo.Date1Date2
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>
 
        </>
    );
}

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

import { Table } from 'funda-ui/Table';
PropertyTypeDefaultDescriptionRequired
refReact.ForwardedRef-It is the return element of this component.-
wrapperClassNamestringmb-3 position-relativeThe class name of the table wrapper.-
tableClassNamestringtableThe class name of the table wrapper.-
dataArray-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
-
dataSelectedArray-Array of numbers, Selected data when rowSelectable is enabled. It's an array of indexed numbers, such as [1,3]
It is valid when rowSelectable is "true"
-
rowDraggablebooleanfalseIndicates whether the per row can be dragged.
The data prop must exist to fire data interaction.
-
rowSelectablebooleanfalseUse of Checkboxes and clickable rows for selection.
The data prop must exist to fire data interaction.
-
colSortablebooleanfalseSupport sort a column (or columns) when the table is built. The components are used in each column of the head.
The data prop must exist to fire data interaction.
<TableCell /> must have attribute data-table-col.
-
keyboardFocusablebooleanfalseUse the arrow keys on your keyboard to focus on each cell.
The data prop must exist to fire data interaction.
-
filterFieldsArray-Fields used for filtering. such as ['name', 'friend']
The data prop must exist to fire data interaction.
-
borderedbooleanfalseAdds borders on all sides of the table and cells-
colGroupbooleanfalseSet the background color of the multiple columns with the <colgroup> and <col> tags-
cellAutoWidthbooleanfalseWidth 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 />does not need to usenowrap` to avoid automatic text wrapping.
-
responsivebooleantrueFor horizontally scrolling tables on the wrapper.-
enhancedResponsivebooleanfalseCreate enhanced responsive tables up to a particular breakpoint.
Valid when the device width is less than or equal to 768px. <TableRow /> and <TableCell /> must have attribute data-table-text.
-
enhancedResponsiveWithScrollBarbooleanfalseCreate 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. <TableCell /> must have attribute data-table-col.
-
onChangeFilterfunction-Call a function when the value changed. It returns one callback value which is the fetched data (Array).-
onChangeRowSelectfunction-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 rowSelectable is "true"
-
onRowDragfunction-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 rowDraggable is "true"
-
onColSortfunction-Call a function when the column sorting succeeds. It returns one callback value which is the fetched data (Array).
It is valid when colSortable is "true"
-
onCellKeyPressedfunction-It fires when use keyboard arrow keys. It returns three callback values.
  1. The first is the cell classname (String)
  2. The second is the current cell (HTMLTableCellElement)
  3. The last is the KeyboardEvent (KeyboardEvent)
It is valid when keyboardFocusable is "true"
-

👉🏼 JSON configuration properties of the data => It can be any array of objects in JSON format.

Table Body

import { TableBody } from 'funda-ui/Table';
PropertyTypeDefaultDescriptionRequired
refReact.ForwardedRef-It is the return element of this component.-
classNamestring-The class name of the table body.-

Table Cell

import { TableCell } from 'funda-ui/Table';
PropertyTypeDefaultDescriptionRequired
refReact.ForwardedRef-It is the return element of this component.-
classNamestring-The class name of the table cell as <td> or <th>.-
activebooleanfalseWhether to activate the current row.-
activeClassNamestringactiveThe class name of actived.-
colSpannumber1The value represents the number of columns to span.-
nowrapbooleanfalseSequences of whitespace will collapse into a single whitespace. Text will never wrap to the next line.-
scopecol | 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';
PropertyTypeDefaultDescriptionRequired
refReact.ForwardedRef-It is the return element of this component.-
classNamestring-The class name of the table head.-

Table Foot

import { TableFoot } from 'funda-ui/Table';
PropertyTypeDefaultDescriptionRequired
refReact.ForwardedRef-It is the return element of this component.-
classNamestring-The class name of the table foot.-

Table Row

import { TableRow } from 'funda-ui/Table';
PropertyTypeDefaultDescriptionRequired
refReact.ForwardedRef-It is the return element of this component.-
classNamestring-The class name of the table row as <tr>.-
activebooleanfalseWhether to activate the current row.-
activeClassNamestringactiveThe class name of actived.-
itemDataJSON Object-Data for each row. such as {name:'David',friend:'Jone',condition:'GOOD'}-

Table Colgroup

import { TableColgroup } from 'funda-ui/Table';
PropertyTypeDefaultDescriptionRequired
refReact.ForwardedRef-It is the return element of this component.-
classNamestring-The class name of the table colgroup.-
lengthnumber-Specifies how many elements a group has.-
captionSidetop | bottomtopThis property puts the content of a table's <caption> on the specified side.-

Table Caption

import { TableCaption } from 'funda-ui/Table';
PropertyTypeDefaultDescriptionRequired
refReact.ForwardedRef-It is the return element of this component.-
classNamestring-The class name of the table caption.-

Filter Input

import { TableFilter } from 'funda-ui/Table';
PropertyTypeDefaultDescriptionRequired
refReact.ForwardedRef-It is the return element of this component.-
classNamestring-The class name of the filter input control.-
placeholderstring-The placeholder of the filter input control.-
labelReactNodenullLabel for filter input control.-
onChangefunction-Call a function when the value of an HTML element is changed. It returns two callback values.
  1. The first is the Control Event (Event)
  2. The last is the fetched data (Array).
-

Toggle Selection

It will be presented in the form of a checkbox.

import { ToggleSelection } from 'funda-ui/Table';
PropertyTypeDefaultDescriptionRequired
refReact.ForwardedRef-It is the return element of this component.-
contentRefReact.ForwardedRef-It exposes the following methods:
  1. contentRef.current.control()
  2. contentRef.current.setSelectAll(false)
  3. contentRef.current.indeterminate(false)
  4. contentRef.current.set(false)
DO NOT USE it in the onChange of this component, otherwise it will cause infinite rendering
-
rownumber-For the current row, set -1 if it is the head area.
classNamestring-The class name of the table caption.-
checkedbooleanfalseIs it selected.-
useRadiobooleanfalseUse radio instead of Checkbox.-
indeterminatebooleanfalseSet a checkbox to indeterminate state.-
valuestring-Set a default value for this control. If unchecked, it will pass an empty value
namestring-Name is not deprecated when used with form fields.-
disabledbooleanfalseWhether it is disabled-
onChangefunction-Call a function when the value of an HTML element is changed. It returns three callback values.
  1. The first is the Control Event (Event)
  2. The second is the current value (Boolean)
  3. The last is the fetched data (Array).
-

Drag Handle Sprite

import { DragHandleSprite } from 'funda-ui/Table';
PropertyTypeDefaultDescriptionRequired
refReact.ForwardedRef-It is the return element of this component.-
classNamestringdrag-triggerThe class name of the filter input control.-
iconReactNode<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';
PropertyTypeDefaultDescriptionRequired
refReact.ForwardedRef-It is the return element of this component.-
classNamestringsort-triggerThe class name of the filter input control.-
fieldTypetext | number | datetextThe type of field that is sorted, which ensures the accuracy of sorting.
iconReactNode<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-