Components
Hooks
Utils
Overview
The HeadlessDataTable
component is a flexible and customizable data table for React applications. It handles pagination and filtering, making it easy to present, navigate, and search through tabular data. With built-in support for custom headers and styles, it provides a user-friendly experience. Utilizing the useDataTable
hook, it efficiently manages data operations and optimizes performance. Whether displaying product listings, user information, or financial data, this component streamlines data presentation and enhances the overall user interface. It saves development time, promotes data organization, and empowers developers to create intuitive and efficient data tables with minimal effort.
Installation
Before using these components, make sure you have already installed the required dependencies, including React and @locoworks/reusejs-toolkit-react-hooks. You can install the dependencies by running below command in terminal.
yarn add @locoworks/reusejs-react-data-table
or
npm install @locoworks/reusejs-react-data-table
External Dependencies:
HeadlessDataTable
components depend on React and the useDataTable
hook from the @locoworks/reusejs-toolkit-react-hooks
package.
Importing:
To use the HeadlessDataTable component in your project, import it into your component.
import { HeadlessDataTable } from "@locoworks/reusejs-react-data-table"
Types/ Exported Components
HeadlessDataTable component uses TypeScript for type checking and define the HeadlessDataTableInterface
interface to specify the prop types. The main exported component is HeadlessDataTable
.
Example
NAME | GENDER | AGE | CONTACT DETAILS | ADDRESS | |
---|---|---|---|---|---|
No results found. |
import React, { useState, useEffect } from "react";
import { HeadlessDataTable } from "@locoworks/reusejs-react-data-table";
const Example = () => {
const [userList, setUserLists] = useState([]);
const fetchData = async (count: number) => {
try {
const response = await fetch(
`https://randomuser.me/api/?results=${count}`,
); // Replace with the API endpoint URL
const data = await response.json();
setUserLists(data.results); // Set the fetched data in the state
} catch (error) {
console.error("Error fetching data:", error);
}
};
const userData: {
Name: string;
Gender: string;
Age: number;
Email: string;
"Contact Details": string;
Address: string;
}[] = [];
userList.forEach((user: any) => {
const userObject = {
Name: `${user.name.title} ${user.name.first} ${user.name.last}`,
Gender: user.gender,
Age: user.dob.age,
Email: user.email,
"Contact Details": user.cell,
Address: `${user.location.city} ${user.location.state} ${user.location.country} ${user.location.postcode}`,
};
userData.push(userObject);
});
const tableHeader = [
"Name",
"Gender",
"Age",
"Email",
"Contact Details",
"Address",
];
const ShowRecordInfo = (
totalPages: number,
totalRecords: number,
currentPage: number,
itemsPerPage: number,
) => {
return (
<>
<div className="flex items-center">
Showing:{" "}
{currentPage < totalPages
? `${currentPage * itemsPerPage}/${totalRecords}`
: `${totalRecords}/${totalRecords}`}
Records.
</div>
<div className="flex items-center">Page : {currentPage}</div>
</>
);
};
useEffect(() => {
fetchData(50);
}, []);
return (
<div className="flex flex-col items-center gap-x-3 justify-center py-10 mt-10 border rounded bg-gray-50">
<HeadlessDataTable
tableData={userData}
itemsPerPage={5}
customTableHeader={tableHeader}
buttonClasses={"bg-gray-200 py-2 px-4 rounded-md text-gray-700 mb-10"}
buttonContainerClasses={"flex justify-between mt-4"}
showDetails={ShowRecordInfo}
tableColumnClasses={"px-4 border border-gray-500"}
tableContainerClasses={"flex flex-col px-10 w-full bg-white"}
tableClasses={"w-full"}
headingColumnClasses={"px-4 text-left border border-gray-500"}
headingRowClasses={"bg-gray-300 "}
/>
</div>
);
};
export default Example;
DataTable (Column Based Filter)
NAME | AGE | CONTACT DETAILS | ADDRESS | ||
---|---|---|---|---|---|
No results found. |
import React, { useState, useEffect } from "react";
import { HeadlessDataTable } from "@locoworks/reusejs-react-data-table";
const FilterDataTable = () => {
const [userList, setUserLists] = useState([]);
const [searchString, setSearchString] = useState<string>("");
const [searchQueries, setSearchQueries] = useState<
{ field: string; value: string }[]
>([]);
const [dropDownValue, setDropDownValue] = useState<string>("default");
const fetchData = async (count: number) => {
try {
const response = await fetch(
`https://randomuser.me/api/?results=${count}`,
); // Replace with the API endpoint URL
const data = await response.json();
setUserLists(data.results); // Set the fetched data in the state
} catch (error) {
console.error("Error fetching data:", error);
}
};
const userData: {
name: string;
gender: string;
age: string;
email: string;
contact_details: string;
address: string;
}[] = [];
userList.forEach((user: any) => {
const userObject = {
name: `${user.name.title} ${user.name.first} ${user.name.last}`,
gender: user.gender,
age: `${user.dob.age}`,
email: user.email,
contact_details: user.cell,
address: `${user.location.country} ${user.location.postcode}`,
};
userData.push(userObject);
});
const tableHeader = [
"name",
"email",
"age",
"email",
"contact_details",
"address",
];
const ShowRecordInfo = (
totalPages: number,
totalRecords: number,
currentPage: number,
itemsPerPage: number,
) => {
return (
<>
<div className="flex items-center">
Showing:{" "}
{currentPage < totalPages
? `${currentPage * itemsPerPage}/${totalRecords}`
: `${totalRecords}/${totalRecords}`}
Records.
</div>
<div className="flex items-center">
Page : {currentPage}/{totalPages}
</div>
</>
);
};
useEffect(() => {
fetchData(50);
}, []);
return (
<div className="flex flex-col items-center gap-x-3 justify-center py-10 mt-10 border rounded bg-gray-50">
<div className="flex mx-10 items-center justify-between">
<select
className="flex py-2 text-xl px-4 rounded-md border border-gray-400 mb-10"
value={dropDownValue}
onChange={(e) => {
setDropDownValue(e.target.value.toString());
}}
>
<option value="default">Select Filter</option>
{tableHeader.map((colunm: string, index: number) => {
return (
<option key={index} value={colunm}>
{colunm}
</option>
);
})}
</select>
<div className="flex justify-center items-center mb-10">
<input
onChange={(e) => {
setSearchString(e.target.value);
if (dropDownValue !== "default") {
setSearchQueries([
{ field: dropDownValue, value: e.target.value },
]);
}
}}
value={searchString}
placeholder="Search Here..."
className="flex py-2 px-4 border border-gray-400 rounded-md mx-10 bg-white"
/>
<button
className="border border-gray-400 rounded-md py-2 px-4 bg-white"
onClick={() => {
setSearchString("");
setSearchQueries([]);
setDropDownValue("default");
}}
>
clear
</button>
</div>
</div>
<HeadlessDataTable
tableData={userData}
itemsPerPage={5}
customTableHeader={tableHeader}
buttonClasses={"bg-gray-200 py-2 px-4 rounded-md text-gray-700 mb-10"}
buttonContainerClasses={"flex justify-between mt-4"}
showDetails={ShowRecordInfo}
tableColumnClasses={"px-4 border border-gray-500"}
tableContainerClasses={"flex flex-col px-10 w-full bg-white"}
tableClasses={"w-full"}
headingColumnClasses={"px-4 text-left border border-gray-500"}
headingRowClasses={"bg-gray-300 "}
queryObject={searchQueries}
searchAll=""
/>
</div>
);
};
export default FilterDataTable;
SearchTable (Search in whole table)
NAME | GENDER | AGE | CONTACT DETAILS | ADDRESS | |
---|---|---|---|---|---|
No results found. |
import React, { useState, useEffect } from "react";
import { HeadlessDataTable } from "@locoworks/reusejs-react-data-table";
const FilterDataTable = () => {
const [userList, setUserLists] = useState([]);
const [searchString, setSearchString] = useState<string>("");
const fetchData = async (count: number) => {
try {
const response = await fetch(
`https://randomuser.me/api/?results=${count}`,
); // Replace with the API endpoint URL
const data = await response.json();
setUserLists(data.results); // Set the fetched data in the state
} catch (error) {
console.error("Error fetching data:", error);
}
};
const userData: {
Name: string;
Gender: string;
Age: string;
Email: string;
"Contact Details": string;
Address: string;
}[] = [];
userList.forEach((user: any) => {
const userObject = {
Name: `${user.name.title} ${user.name.first} ${user.name.last}`,
Gender: user.gender,
Age: `${user.dob.age}`,
Email: user.email,
"Contact Details": user.cell,
Address: `${user.location.country} ${user.location.postcode}`,
};
userData.push(userObject);
});
const tableHeader = [
"Name",
"Gender",
"Age",
"Email",
"Contact Details",
"Address",
];
const ShowRecordInfo = (
totalPages: number,
totalRecords: number,
currentPage: number,
itemsPerPage: number,
) => {
return (
<div className="flex items-center mt-10">
Showing: {currentPage * itemsPerPage - (itemsPerPage - 1)} to{" "}
{currentPage * itemsPerPage} of {totalRecords} results
</div>
);
};
useEffect(() => {
fetchData(50);
}, []);
return (
<div className="flex flex-col items-center gap-x-3 justify-center py-10 mt-10 border rounded bg-gray-50">
<div className="flex justify-center items-center mb-10">
<input
onChange={(e) => {
setSearchString(e.target.value);
}}
value={searchString}
placeholder="Search Here..."
className="flex py-2 px-4 border border-gray-400 rounded-md mx-10 bg-white"
/>
<button
className="border border-gray-400 rounded-md py-2 px-4 bg-white"
onClick={() => {
setSearchString("");
}}
>
clear
</button>
</div>
<HeadlessDataTable
tableData={userData}
itemsPerPage={5}
customTableHeader={tableHeader}
buttonClasses={
"bg-gray-200 py-2 px-4 rounded-md text-gray-700 mb-10 mx-4"
}
buttonContainerClasses={"flex justify-end relative -top-9"}
showDetails={ShowRecordInfo}
tableColumnClasses={"px-4 border border-gray-500"}
tableContainerClasses={"flex flex-col px-10 w-full bg-white"}
tableClasses={"w-full"}
headingColumnClasses={"px-4 text-left border border-gray-500"}
headingRowClasses={"bg-gray-300 "}
queryObject={[]}
searchAll={searchString}
/>
</div>
);
};
export default FilterDataTable;
NestedSearchTable
NAME | GENDER | AGE | CONTACT DETAILS | ADDRESS | |
---|---|---|---|---|---|
No results found. |
import React, { useState, useEffect } from "react";
import { HeadlessDataTable } from "@locoworks/reusejs-react-data-table";
import { ReuseInput } from "@locoworks/reusejs-react-input";
import { HeadlessButton } from "@locoworks/reusejs-react-button";
const FilterDataTable = () => {
const [userList, setUserLists] = useState([]);
const [searchQueries, setSearchQueries] = useState<
{
field: string;
value: string;
}[]
>([]);
const [nameField, setNameField] = useState("");
const [emailField, setEmailField] = useState("");
const [addressField, setAddressField] = useState("");
const fetchData = async (count: number) => {
try {
const response = await fetch(
`https://randomuser.me/api/?results=${count}`,
); // Replace with the API endpoint URL
const data = await response.json();
setUserLists(data.results); // Set the fetched data in the state
} catch (error) {
console.error("Error fetching data:", error);
}
};
const userData: {
Name: string;
Gender: string;
Age: string;
Email: string;
"Contact Details": string;
Address: string;
}[] = [];
userList.forEach((user: any) => {
const userObject = {
Name: `${user.name.title} ${user.name.first} ${user.name.last}`,
Gender: user.gender,
Age: `${user.dob.age}`,
Email: user.email,
"Contact Details": user.cell,
Address: `${user.location.country} ${user.location.postcode}`,
};
userData.push(userObject);
});
const tableHeader = [
"Name",
"Gender",
"Age",
"Email",
"Contact Details",
"Address",
];
const ShowRecordInfo = (
totalPages: number,
totalRecords: number,
currentPage: number,
itemsPerPage: number,
) => {
return (
<div className="flex items-center mt-10">
Showing: {currentPage * itemsPerPage - (itemsPerPage - 1)} to{" "}
{currentPage * itemsPerPage} of {totalRecords} results
</div>
);
};
const prepareSearchPayload = (
name: string,
email: string,
address: string,
) => {
let namePayload;
let emailPayload;
let addressPayload;
const queryObject: { field: string; value: string }[] = [];
if (name !== "") {
namePayload = { field: "Name", value: name };
setSearchQueries([...searchQueries, namePayload]);
queryObject.push(namePayload);
}
if (email !== "") {
emailPayload = { field: "Email", value: email };
queryObject.push(emailPayload);
}
if (address !== "") {
addressPayload = { field: "Address", value: address };
queryObject.push(addressPayload);
}
setSearchQueries(queryObject);
};
useEffect(() => {
fetchData(50);
}, []);
return (
<div className="flex flex-col items-center gap-x-3 justify-center py-10 mt-10 border rounded bg-gray-50">
<div className="flex justify-center items-center mb-10">
<ReuseInput
placeholder="Search Name..."
className="flex mx-4"
onChange={(e) => {
setNameField(e.target.value);
}}
value={nameField}
/>
<ReuseInput
placeholder="Search Email..."
className="flex mx-4"
onChange={(e) => {
setEmailField(e.target.value);
}}
value={emailField}
/>
<ReuseInput
placeholder="Search Address"
className="flex mx-4"
onChange={(e) => {
setAddressField(e.target.value);
}}
value={addressField}
/>
<HeadlessButton
className="bg-blue-200 border border-blue-400 rounded px-3 py-1 mx-2"
onClick={() => {
prepareSearchPayload(nameField, emailField, addressField);
}}
>
Search
</HeadlessButton>
<HeadlessButton
className="bg-blue-200 border border-blue-400 rounded px-3 py-1"
onClick={() => {
setNameField("");
setEmailField("");
setAddressField("");
setSearchQueries([]);
}}
>
Clear Search
</HeadlessButton>
</div>
<HeadlessDataTable
tableData={userData}
itemsPerPage={5}
customTableHeader={tableHeader}
buttonClasses={
"bg-gray-200 py-2 px-4 rounded-md text-gray-700 mb-10 mx-4"
}
buttonContainerClasses={"flex justify-end relative -top-9"}
showDetails={ShowRecordInfo}
tableColumnClasses={"px-4 border border-gray-500"}
tableContainerClasses={"flex flex-col px-10 w-full bg-white"}
tableClasses={"w-full"}
headingColumnClasses={"px-4 text-left border border-gray-500"}
headingRowClasses={"bg-gray-300 "}
queryObject={searchQueries}
searchAll=""
/>
</div>
);
};
export default FilterDataTable;
Props Table
Apologies for the oversight. Here is the corrected markdown table including the missing showDetails
and customTableHeader
:
Prop | Type | Description |
---|---|---|
tableData | Array of Object | An array of objects representing the data for the table. Each object represents a row, and its properties represent columns. |
itemsPerPage | Number | An integer representing the number of items to display per page. If set to 0 or not provided, all data will be displayed on a single page without pagination. |
queryAll | String | A string representing a global search query applied to the entire table. This allows users to search for a specific term across all columns. |
searchQueryObject | Array of Object | An array of search query objects that allow filtering the data based on specific column values. Each object in the array should have two properties: field (string) - The name of the column to filter, value (string) - The value to search for in the specified column. |
tableContainerClasses | String/Object | Custom CSS classes or styles to be applied to the container element that wraps the table. Accepts either a string of space-separated class names or an object of inline styles. |
tableClasses | String/Object | Custom CSS classes or styles to be applied to the table element. Accepts either a string of space-separated class names or an object of inline styles. |
tableRowClasses | String/Object | Custom CSS classes or styles to be applied to the table rows (tr elements). Accepts either a string of space-separated class names or an object of inline styles. |
tableColumnClasses | String/Object | Custom CSS classes or styles to be applied to the table columns (td elements). Accepts either a string of space-separated class names or an object of inline styles. |
headingRowClasses | String/Object | Custom CSS classes or styles to be applied to the heading row (tr element) of the table. Accepts either a string of space-separated class names or an object of inline styles. |
headingColumnClasses | String/Object | Custom CSS classes or styles to be applied to the heading columns (th elements) of the table. Accepts either a string of space-separated class names or an object of inline styles. |
buttonClasses | String/Object | Custom CSS classes or styles to be applied to the navigation buttons. Accepts either a string of space-separated class names or an object of inline styles. |
buttonContainerClasses | String/Object | Custom CSS classes or styles to be applied to the container element that wraps the navigation buttons. Accepts either a string of space-separated class names or an object of inline styles. |
showDetails | Function | A function that receives totalPages, totalItems, currentPage, and itemsPerPage as arguments. This function can be used to display additional information about the pagination or any custom details based on the current state of the data table. |
customTableHeader | Array of Object | An array of strings representing the table header. If not provided, the table header will be created from the tableData. |
Note:
- If you're looking to harness the power of the Simple
DataTable
withPagination
, or if you find the need for additional features likeSearch
andFilter
functionalities alongsidePagination
, then the recommended choice is theHeadlessDataTable
. - The
HeadlessDataTable
component seamlessly integrates theuseDataTable
hook from the@locoworks/reusejs-toolkit-react-hooks
library. This hook efficiently managespagination
and various other functionalities, providing a range of properties for rendering the table and handlingpagination
. For a more in-depth understanding, please refer to the dedicated hook section. - Utilizing the
HeadlessDataTable
component automates thepagination
of yourtableData
based on the