react-dynamiq-table
Version:
this is react dynamic table help you to avoide repeating yourself. it's very easy to customize the style and access your data dynamically without mapping
311 lines (265 loc) • 19.4 kB
Markdown
# React Dynamiq Table
## Overview
The **DynamicTable** component is a flexible, customizable table designed for rendering lists of data. It provides a wide range of options to control the display, structure, and actions within the table. This component supports features such as pagination, custom actions, and dynamic content rendering, making it a powerful tool for building interactive and data-driven tables in your applications.
With **DynamicTable**, you can dynamically modify props without (**map**) like columns, normalProps, useLink and more. This allows you to configure the table based on the specific needs of your app, while keeping the implementation simple and straightforward.
The table’s customizability ensures that you can easily tailor it to fit your design, data, and functionality requirements.
# Project Setup Instructions
## Required Dependencies
- `react@19`
- `react-dom@19`
- `tailwindcss`
## Props
`DynamicTable` accepts the following props:
| Prop | Type | Description |
| ----------------------- | ----------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
| **`tableName`** | `string` (Optional) | Name of the table, useful for debugging or analytics. |
| **`topContent`** | `ReactNode` (Optional) | Custom content to be displayed above the table (e.g., filters, headers) if you don't want to use the default top content. |
| **`topContentOptions`** | `TopContentOptionsType` (Optional) | Configuration options for `default topContent`, allowing further customization. |
| **`columns`** | `ColumnType<NestedFieldPaths<T>>[]` (Required) | Array of column definitions for the table. |
| **`items`** | `T[]` (Required) | Array of data to be displayed in the table. |
| **`emptyContent`** | `ReactNode` (Optional) | Content to display when there are no items available. |
| **`isLoading`** | `boolean` (Optional) | Flag to show loading state. |
| **`loadingContent`** | `ReactNode` (Optional) | Custom content displayed during loading. |
| **`tBodyProps`** | `HTMLProps<HTMLTableSectionElement>` (Optional) | Additional props for the table body (`<tbody>`). |
| **`tHeadProps`** | `HTMLProps<HTMLTableSectionElement>` (Optional) | Additional props for the table header (`<thead>`). |
| **`tHeadTrProps`** | `HTMLProps<HTMLTableRowElement>` (Optional) | Additional props for the rows within the table header. |
| **`tBodyTrProps`** | `HTMLProps<HTMLTableRowElement>` (Optional) | Additional props for the rows within the table body. |
| **`baseProps`** | `HTMLProps<HTMLDivElement>` (Optional) | Props for the container wrapping the table. |
| **`tableBaseProps`** | `HTMLProps<HTMLDivElement>` (Optional) | Props for the main table wrapper div. |
| **`tableProps`** | `HTMLProps<HTMLTableElement>` (Optional) | Additional props for the `<table>` element itself. |
| **`actions`** | `ActionsType[]` (Optional) | Array of actions (e.g., "Edit", "Delete", etc.) for rows or the entire table. |
| **`actionColumName`** | `string` (Optional) | Name of the column where action buttons will be rendered. |
| **`usePagination`** | `boolean` (Required) | Flag to enable or disable pagination. |
| **`pagination`** | `PAGINATION_TYPE` (Optional) | Pagination configuration such as current page, items per page, etc. |
# ColumnType Props
The `ColumnType` defines the configuration for each column in the `DynamicTable`. It provides various options for customizing how the column behaves, displays, and interacts with the data. The following table describes the available properties for `ColumnType`:
| Prop | Type | Description |
| ------------------- | ------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------ |
| **`columnName`** | `string` | The name of the column, used for display as TH and as a key in data processing. |
| **`accessor`** | `K` (Optional) | The key or path used to access the value from the data for this column. |
| **`static`** | `string | number` (Optional) | A static value that can be used as the column content instead of dynamic data. |
| **`showIf`** | `boolean` (Optional) | Determines if the column should be displayed. |
| **`conditions`** | `ColumnConditionsType<K>[]` (Optional) | Array of conditions to apply to the column the date you want to show base on condition. |
| **`useCondition`** | `boolean` (Optional) | Flag to enable or disable conditions for the column. |
| **`rename`** | `string` (Optional) | Allows renaming the column header. |
| **`useDate`** | `boolean` (Optional) | Flag to format the column value as a date (use with date values). |
| **`join`** | `K[]` (Optional) | List of columns to join for this column (e.g., for combining multiple columns). |
| **`useAction`** | `boolean` (Optional) | Flag to enable or disable actions for this column |
| **`actionOptions`** | `ActionsType` (Optional) | Custom configuration for actions in this column. |
| **`useOption`** | `boolean` (Optional) | Flag to enable options for this column (e.g., dropdowns, select options). |
| **`optionOptions`** | `OptionOptions` (Optional) | Custom configuration for options in this column (e.g., data). |
| **`useLink`** | `boolean` (Optional) | Flag to turn this column into a link (useful for linking to details page dynamicaly etc.). |
| **`linkOptions`** | `LinkOptionsType` (Optional) | Configuration for the link behavior in this column. |
| **`useChip`** | `boolean` (Optional) | Flag to display the column as a chip (useful for labels or statuses). |
| **`chipOptions`** | `ChipOptions` (Optional) | Configuration for how the chip should be displayed (e.g., colors, styles). |
| **`normalProps`** | `{ th?: HTMLProps<HTMLTableColElement>; td?: HTMLProps<HTMLTableCellElement>; }` (Optional) | Additional HTML props for the column's header (`th`) and cells (`td`). |
# LinkOptionsType Props
The `LinkOptionsType` defines the configuration for a link that can be used within a column in the `DynamicTable`. It allows you to customize the behavior of the link for each column, such as setting the `href` or making it dynamic.
The following table describes the available properties for `LinkOptionsType`:
| Prop | Type | Description |
| ---------- | ------------------- | --------------------------------------------------------------------------------------------------------------------- |
| **`href`** | `string` (Optional) | The URL or path the link will navigate to when clicked. It can be static or dynamically set based on the column data. |
## Example Usage
Here’s how you can configure a column to use `LinkOptionsType` in the `DynamicTable`:
````tsx
const columns: ColumnType<string>[] = [
{
columnName: "Profile",
accessor: "profileUrl",
useLink: true,
linkOptions: {
href: "/profile/[id]",
},
},
];
# ColumnConditionsType Props
The `ColumnConditionsType` defines conditions that can be applied to columns within the `DynamicTable`. This allows for conditional rendering of data in specific columns based on predefined conditions, making it easy to customize how table data is displayed.
The following table describes the available properties for `ColumnConditionsType`:
| Prop | Type | Description |
|------------|------------------------------------------------|-----------------------------------------------------------------------------|
| **`condtion`** | `boolean | { compare: string[] }` (Required) | Defines the condition for displaying a column's data. It can either be a simple boolean or an object with an array of strings that specify conditions for comparison. |
| **`redner`** | `ColumnConditionsRenderType<T>` (Required) | The rendering function or configuration for the column when the condition is met. It defines how the column's data should be rendered if the condition is satisfied. |
### Note:
You can make conditions dynamic from your data inside `"[]"`, while static values should be enclosed in `" "`. For example:
- **Dynamic condition**: `["[status]", 'active']` – Here, the condition will be evaluated based on the data in `status`.
- **Static condition**: `["age", '18']` – This will be a fixed condition.
---
## Example Usage
Here’s an example showing how you can use the `ColumnConditionsType` in the `DynamicTable`:
```tsx
const columns: ColumnType<string>[] = [
{
columnName: "Status",
accessor: "status",
conditions: [
{
condtion: { compare: ["[status]", "pending"] }, // Only show if status is equal to "pending"
render: {
accessor: "status", // The status will be displayed if the condition is met
}
},
{
condtion: { compare: ["completed", "completed"] }, // Only show if status as static value of "completed" is equal to "completed"
render: {
accessor: "status", // The status will be displayed if the condition is met
}
},
],
},
];
# DynamicTable Example
The `DynamicTable` component is a flexible and customizable table that can be configured dynamically with various props for rendering lists of data. Below is an example of how you can implement a `DynamicTable` for displaying teacher information.
---
### Example Usage:
```tsx
<DynamicTable<TEACHERCOUNTINTERFACE>
baseProps={{
className: "!rounded-none", // Apply additional styles to the table container
}}
topContentOptions={{
addButton: {
startContent: <PlusIcon />, // Add icon to the "Add New Teacher" button
title: "Add New Teacher", // Button title
onClick: () => {
onOpenChoseTheWayToAddTeacherModal(); // Open modal when button clicked
},
className: "!py-1 !bg-black", // Button styles
},
searchInput: {
onChange: (e: any) => {
setSearchInput(e.target.value); // Update search input state
},
value: searchInput, // Bind value to the search input field
placeholder: "Search Teacher", // Search field placeholder text
},
}}
emptyContent={<>you've not added any teachers yet</>} // Message when no data is available
tableName="Teachers" // Table name for identification and debugging
isLoading={fetchTeachersLoading} // Flag to show loading state
loadingContent={<LoadingSpiner />} // Custom content to show while loading
items={teachersData} // Data to be displayed in the table
columns={[
{
accessor: "teacher.firstName", // Data field to be displayed in this column
columnName: "Name", // Column header
join: [
"teacher.firstName",
"teacher.middleName",
"teacher.lastName", // Join multiple fields to display the full name
],
},
{
accessor: "teacher.email", // Email field for each teacher
columnName: "Email",
},
{
accessor: "teacher.emailVerified", // Verification status for the teacher's email
columnName: "Verified",
},
{
accessor: "teacher.primaryPhoneNumber", // Primary phone number field
columnName: "Number",
},
{
accessor: "teacher.phoneNumberVerified", // Verification status for phone number
columnName: "Verified",
},
{
columnName: "Subjects", // Number of subjects taught by the teacher
accessor: "subjectsCount",
normalProps: {
td: {
className: "text-center", // Center align the text in the cell
},
},
},
{
columnName: "Classes", // Number of classes assigned to the teacher
accessor: "classCount",
normalProps: {
td: {
className: "text-center", // Center align the text in the cell
},
},
},
{
accessor: "requestStatus", // Request status (e.g., pending, accepted)
columnName: "Status",
useChip: true, // Use a chip component to display status
chipOptions: {
className:
"{[requestStatus] === 'accepted' ? 'w-2 h-2 bg-green-600' : 'w-2 h-2 bg-red-600'}", // Conditional chip styling based on status
},
},
{
accessor: "createdBy.firstName", // Teacher's creator (e.g., admin who added the teacher)
columnName: "Created By",
join: [
"createdBy.firstName",
"createdBy.middleName",
"createdBy.lastName", // Join full name of the creator
],
},
{
accessor: "createdAt", // Date when the teacher was added
columnName: "Created At",
useDate: true, // Use date formatting for this column
},
{
accessor: "createdAt", // Column for Actions (e.g., verification)
columnName: "Actions",
useAction: true, // Enable actions for this column
actionOptions: {
components(data) {
return (
<div>
<p>Verify Teacher</p> // Action component for verifying teacher
</div>
);
},
},
},
]}
usePagination={true} // Enable pagination
pagination={{
page: Number(page), // Current page number
per_page: Number(per_page), // Number of items per page
totalPages: pages, // Total number of pages
handlePageChange(page) {
if (search) {
router.push(
`/pages/${schoolId}/teachers?per_page=${per_page}&page=${page}&search=${search}` // Handle page change with search filter
);
} else {
router.push(
`/pages/${schoolId}/teachers?per_page=${per_page}&page=${page}` // Handle page change without search filter
);
}
},
per_pageComponent: (
<>
<select name="name" id="id">
<option value={5}>5</option>
</select>
</>
), // Pagination component to select number of items per page
}}
/>
````
## `normalProps` Usage
The `normalProps` object allows you to customize the `<th>` (table header) and `<td>` (table data) elements for each column. Both `th` and `td` properties accept any valid HTML attributes, such as `className`, `style`, `id`, etc. You can conditionally modify these properties using **ternary conditions** enclosed by `{}` and dynamically access data within your rows using `[]`.
### Note:
- **String properties** like `className`, `id`, etc., can be conditionally set using **ternary conditions** enclosed in `{}`.
- You can access values from your data dynamically by referencing the properties inside `[]` (e.g., `[teacher.status]`).
### Example:
In the following example, the `className` for both `<th>` and `<td>` is conditionally set based on the `status` of the teacher. The ternary operator is used to apply different values for the class based on the value of `teacher.status` and make sure your result is in between '' .
```tsx
normalProps: {
th: {
className: "{[teacher.status] === 'pending' ? 'bg-yellow-500' : [teacher.status] === 'accepted' ? 'bg-green-500' : 'bg-gray-500'}", // Apply a background color based on teacher's status
},
td: {
className: "{[status] === 'pending' ? 'text-blue-300' : [teacher.status] === 'reject' ? 'text-red-900' : 'text-green'}", // Apply text color based on status
}
}
```