React - creating dynamic data table using primereact library
I am trying a create a reusable custom data table in React (tsx). I want to use the primereact library to create it. I want it to create it in a dynamic way that it should be able to handle sorting, dynamic type of data that is coming into the table (if it is date, it should format date, if it is text it should format that...) and so on.
import React, { Component, ReactNode } from "react";
import { DataTable } from "primereact/datatable";
import { Checkbox } from "primereact/checkbox";
import { Column, ColumnProps } from "primereact/column";
import "primereact/resources/themes/mdc-dark-deeppurple/theme.css";
import "primereact/resources/primereact.min.css";
import "primeicons/primeicons.css";
import { PaginatorComponent } from "./paginatorComponent";
import "./customDataTable.css";
// Define the properties that the CustomDataTable component expects as input.
interface DataTableProps {
data: any[]; // Input: The data to display in the table.
checkbox: boolean; // Input: Indicates whether to show checkboxes for row selection.
sortField: string | null; // Input: The field used for sorting.
sortOrder: number; // Input: The sorting order (1 for ascending, -1 for descending).
onSortChange: (field: string, order: number) => void; // Output: Callback for sorting change.
onSelectionChange: (selectedRows: any[], selectAll: boolean) => void; // Output: Callback for selection change.
scrollHeight?: string; // Input: Height for the table with a scrollbar.
scrollWidth?: string; // Input: Width for the table with a scrollbar.
columnRenderers?: Record<string, (cellData: any) => ReactNode>; // Input: Renderers for custom column data.
children?: ReactNode; // Child components, which are the columns of the table.
scrollable?: boolean; // Input: Indicates whether the table should be scrollable.
}
// Define the state structure for the CustomDataTable component.
interface DataTableState {
currentPage: number; // Current page of the table.
selectedRows: any[]; // Selected rows in the table.
dataToDisplay: any[]; // Data to display in the table.
selectAll: boolean; // Indicates whether all rows are selected.
itemsPerPage: number; // Number of items to display per page.
}
// Define the CustomDataTable component.
class CustomDataTable extends Component<DataTableProps, DataTableState> {
// Constructor for the component, initializing state and binding methods.
constructor(props: DataTableProps) {
super(props);
this.state = {
currentPage: 1,
selectedRows: [],
dataToDisplay: this.props.data,
selectAll: false,
itemsPerPage: 3,
};
}
// componentDidUpdate is called when props change, used for sorting updates.
componentDidUpdate(prevProps: DataTableProps, prevState: DataTableState) {
if (
prevProps.data !== this.props.data ||
prevProps.sortField !== this.props.sortField ||
prevProps.sortOrder !== this.props.sortOrder
) {
this.sortData();
}
}
// Callback for changing the current page.
handlePageChange = (newPage: number) => {
this.setState({ currentPage: newPage });
}; // Toggle the selection of all rows in the table.
toggleAllRows = () => {
const { selectAll, dataToDisplay } = this.state;
if (selectAll) {
// If all rows are already selected, clear the selection.
this.setState({ selectedRows: [] });
} else {
// If not all rows are selected, select all of them.
this.setState({ selectedRows: [...dataToDisplay] });
} // Toggle the selectAll flag and trigger the onSelectionChange callback.
this.setState({ selectAll: !selectAll }, () => {
this.props.onSelectionChange(this.state.selectedRows, !selectAll);
});
};
// Toggle the selection of a single row.
toggleRow = (rowData: any) => {
const { selectedRows } = this.state;
const rowIndex = selectedRows.findIndex((row) => row.id === rowData.id);
if (rowIndex === -1) {
// If the row is not selected, add it to the selection.
this.setState(
{ selectedRows: [...selectedRows, rowData], selectAll: false },
() => {
this.props.onSelectionChange(this.state.selectedRows, false);
}
);
} else {
// If the row is already selected, remove it from the selection.
const newSelectedRows = [...selectedRows];
newSelectedRows.splice(rowIndex, 1);
this.setState({ selectedRows: newSelectedRows, selectAll: false }, () => {
this.props.onSelectionChange(newSelectedRows, false);
});
}
};
// Sort the data based on the selected sort field and order.
sortData = () => {
const { sortField, sortOrder } = this.props;
if (sortField) {
// Create a sorted copy of the data based on the sortField and sortOrder.
const sorted = [...this.state.dataToDisplay].sort((a, b) => {
const aValue = a[sortField];
const bValue = b[sortField]; // Determine if the field values are numerical.
const isNumerical = !isNaN(parseFloat(aValue)) && !isNaN(parseFloat(bValue));
let result = 0;
if (isNumerical) {
// If the values are numerical, compare them directly.
result = sortOrder === 1 ? aValue - bValue : bValue - aValue;
} else {
// If the values are not numerical, perform a string-based comparison.
result = sortOrder === 1 ? aValue.localeCompare(bValue) : bValue.localeCompare(aValue);
}
return result;
});
// Update the dataToDisplay state with the sorted data.
this.setState({ dataToDisplay: sorted });
}
};
// Callback for changing the number of items per page.
handleItemsPerPageChange = (itemsPerPage: number) => {
this.setState({ itemsPerPage }, () => {
this.updateDisplayedData();
});
};
// Update the displayed data based on the current page and items per page.
updateDisplayedData = () => {
const { currentPage, itemsPerPage } = this.state;
const startIndex = (currentPage - 1) * itemsPerPage;
const endIndex = startIndex + itemsPerPage;
const dataToDisplayPaginated = this.state.dataToDisplay.slice(
startIndex,
endIndex
);
console.log(dataToDisplayPaginated);
};
// Callback for sorting column data when a column header is clicked.
handleSortClick = (field: string) => {
const { sortField, sortOrder } = this.props;
if (field === sortField) {
this.props.onSortChange(field, sortOrder === 1 ? -1 : 1);
} else {
this.props.onSortChange(field, 1);
}
};
// Lifecycle method called after the component is mounted.
componentDidMount() {
console.log(`Initial Sorting Direction: ${this.props.sortOrder}`);
}
// Render method for the component.
render() {
const {
currentPage,
selectedRows,
dataToDisplay,
selectAll,
itemsPerPage,
} = this.state;
const { checkbox } = this.props; // Calculate the index range for the current page.
const startIndex = (currentPage - 1) * itemsPerPage;
const endIndex = startIndex + itemsPerPage;
const dataToDisplayPaginated = dataToDisplay.slice(startIndex, endIndex);
return (
<div className="custom-data-table-container">
{" "}
<div className="custom-data-table">
{" "}
<DataTable
value={dataToDisplayPaginated}
stripedRows
scrollable
className="custom-data-table-scroll"
>
{" "}
{/* Check if the checkbox option is enabled and add checkbox column if true. */}
{" "}
{checkbox && (
<Column
key="checkbox"
header={
<Checkbox
className="custom-checkbox"
checked={selectAll}
onChange={this.toggleAllRows}
/>
}
body={(rowData) => (
<Checkbox
className="custom-checkbox"
checked={selectedRows.some((row) => row.id === rowData.id)}
onChange={() => this.toggleRow(rowData)}
/>
)}
/>
)}
{" "}
{React.Children.map(this.props.children, (child: ReactNode) => {
// Use React.Children.map to iterate over the child elements passed to the component.
if (React.isValidElement<ColumnProps>(child)) {
// Check if the child is a valid React element with a specific type, here Column component.
return React.cloneElement(
child as React.ReactElement<ColumnProps>,
{
// Clone the child element and potentially modify its props.
// child as React.ReactElement<ColumnProps> casts the child element as a Column with specific props.
}
);
}
// If the child is not a valid Column component, return null.
return null;
})}
{" "}
</DataTable>
{" "}
</div>
{" "}
<PaginatorComponent
totalItems={this.props.data.length}
itemsPerPage={itemsPerPage}
currentPage={currentPage}
onPageChange={this.handlePageChange}
rowsCountOptions={[3, 5, 10, 20]}
/>
{" "}
</div>
);
}
}
// Export the CustomDataTable component.
export default CustomDataTable;
Attaching my code for reference, I added comments so that you wil not confuse. I need help in creating the row renderer function, so that I can pass dynamic data without again defining what kind of data it is in my component where I am using this data table. If i date in my dynamic data, it should be able to pass it in date format. If it is text it should be able to pass that format. Please help me with this, as I am a beginner to this. Thanks in advance
Automatically generated columns can be achieved using:
import React, { Component, ReactNode } from "react";
import { DataTable } from "primereact/datatable";
import { Checkbox } from "primereact/checkbox";
import { Column, ColumnProps } from "primereact/column";
import "primereact/resources/themes/mdc-dark-deeppurple/theme.css";
import "primereact/resources/primereact.min.css";
import "primeicons/primeicons.css";
import { PaginatorComponent } from "./paginatorComponent";
import "./customDataTable.css";
// Source: https://dirask.com/snippets/JavaScript-detect-column-names-in-data-rows-D9ooaj
//
const findColumns = (rows: any[]): string[] => {
const columns = {} as Record<string, true>;
for (const row of rows) {
for (const name in row) {
columns[name] = true;
}
}
return Object.keys(columns);
};
// Define the properties that the CustomDataTable component expects as input.
interface DataTableProps {
data: any[]; // Input: The data to display in the table.
checkbox: boolean; // Input: Indicates whether to show checkboxes for row selection.
sortField: string | null; // Input: The field used for sorting.
sortOrder: number; // Input: The sorting order (1 for ascending, -1 for descending).
onSortChange: (field: string, order: number) => void; // Output: Callback for sorting change.
onSelectionChange: (selectedRows: any[], selectAll: boolean) => void; // Output: Callback for selection change.
scrollHeight?: string; // Input: Height for the table with a scrollbar.
scrollWidth?: string; // Input: Width for the table with a scrollbar.
children?: ReactNode; // Child components, which are the columns of the table.
scrollable?: boolean; // Input: Indicates whether the table should be scrollable.
}
// Define the state structure for the CustomDataTable component.
interface DataTableState {
currentPage: number; // Current page of the table.
selectedRows: any[]; // Selected rows in the table.
dataToDisplay: any[]; // Data to display in the table.
selectAll: boolean; // Indicates whether all rows are selected.
itemsPerPage: number; // Number of items to display per page.
}
// Define the CustomDataTable component.
class CustomDataTable extends Component<DataTableProps, DataTableState> {
// Constructor for the component, initializing state and binding methods.
constructor(props: DataTableProps) {
super(props);
this.state = {
currentPage: 1,
selectedRows: [],
dataToDisplay: this.props.data,
selectAll: false,
itemsPerPage: 3,
};
}
// componentDidUpdate is called when props change, used for sorting updates.
componentDidUpdate(prevProps: DataTableProps, prevState: DataTableState) {
if (
prevProps.data !== this.props.data ||
prevProps.sortField !== this.props.sortField ||
prevProps.sortOrder !== this.props.sortOrder
) {
this.sortData();
}
}
// Callback for changing the current page.
handlePageChange = (newPage: number) => {
this.setState({ currentPage: newPage });
}; // Toggle the selection of all rows in the table.
toggleAllRows = () => {
const { selectAll, dataToDisplay } = this.state;
if (selectAll) {
// If all rows are already selected, clear the selection.
this.setState({ selectedRows: [] });
} else {
// If not all rows are selected, select all of them.
this.setState({ selectedRows: [...dataToDisplay] });
} // Toggle the selectAll flag and trigger the onSelectionChange callback.
this.setState({ selectAll: !selectAll }, () => {
this.props.onSelectionChange(this.state.selectedRows, !selectAll);
});
};
// Toggle the selection of a single row.
toggleRow = (rowData: any) => {
const { selectedRows } = this.state;
const rowIndex = selectedRows.findIndex((row) => row.id === rowData.id);
if (rowIndex === -1) {
// If the row is not selected, add it to the selection.
this.setState(
{ selectedRows: [...selectedRows, rowData], selectAll: false },
() => {
this.props.onSelectionChange(this.state.selectedRows, false);
}
);
} else {
// If the row is already selected, remove it from the selection.
const newSelectedRows = [...selectedRows];
newSelectedRows.splice(rowIndex, 1);
this.setState({ selectedRows: newSelectedRows, selectAll: false }, () => {
this.props.onSelectionChange(newSelectedRows, false);
});
}
};
// Sort the data based on the selected sort field and order.
sortData = () => {
const { sortField, sortOrder } = this.props;
if (sortField) {
// Create a sorted copy of the data based on the sortField and sortOrder.
const sorted = [...this.state.dataToDisplay].sort((a, b) => {
const aValue = a[sortField];
const bValue = b[sortField]; // Determine if the field values are numerical.
const isNumerical = !isNaN(parseFloat(aValue)) && !isNaN(parseFloat(bValue));
let result = 0;
if (isNumerical) {
// If the values are numerical, compare them directly.
result = sortOrder === 1 ? aValue - bValue : bValue - aValue;
} else {
// If the values are not numerical, perform a string-based comparison.
result = sortOrder === 1 ? aValue.localeCompare(bValue) : bValue.localeCompare(aValue);
}
return result;
});
// Update the dataToDisplay state with the sorted data.
this.setState({ dataToDisplay: sorted });
}
};
// Callback for changing the number of items per page.
handleItemsPerPageChange = (itemsPerPage: number) => {
this.setState({ itemsPerPage }, () => {
this.updateDisplayedData();
});
};
// Update the displayed data based on the current page and items per page.
updateDisplayedData = () => {
const { currentPage, itemsPerPage } = this.state;
const startIndex = (currentPage - 1) * itemsPerPage;
const endIndex = startIndex + itemsPerPage;
const dataToDisplayPaginated = this.state.dataToDisplay.slice(
startIndex,
endIndex
);
console.log(dataToDisplayPaginated);
};
// Callback for sorting column data when a column header is clicked.
handleSortClick = (field: string) => {
const { sortField, sortOrder } = this.props;
if (field === sortField) {
this.props.onSortChange(field, sortOrder === 1 ? -1 : 1);
} else {
this.props.onSortChange(field, 1);
}
};
// Lifecycle method called after the component is mounted.
componentDidMount() {
console.log(`Initial Sorting Direction: ${this.props.sortOrder}`);
}
// Render method for the component.
render() {
let columnNames = findColumns(this.props.data); // <----------------------- https://dirask.com/snippets/JavaScript-detect-column-names-in-data-rows-D9ooaj
const {
currentPage,
selectedRows,
dataToDisplay,
selectAll,
itemsPerPage,
} = this.state;
const { checkbox } = this.props; // Calculate the index range for the current page.
const startIndex = (currentPage - 1) * itemsPerPage;
const endIndex = startIndex + itemsPerPage;
const dataToDisplayPaginated = dataToDisplay.slice(startIndex, endIndex);
return (
<div className="custom-data-table-container">
{" "}
<div className="custom-data-table">
{" "}
<DataTable
value={dataToDisplayPaginated}
stripedRows
scrollable
className="custom-data-table-scroll"
>
{" "}
{/* Check if the checkbox option is enabled and add checkbox column if true. */}
{" "}
{checkbox && (
<Column
key="checkbox"
header={
<Checkbox
className="custom-checkbox"
checked={selectAll}
onChange={this.toggleAllRows}
/>
}
body={(rowData) => (
<Checkbox
className="custom-checkbox"
checked={selectedRows.some((row) => row.id === rowData.id)}
onChange={() => this.toggleRow(rowData)}
/>
)}
/>
)}
{" "}
{columnNames.map((columnName: string, columnIndex: number) => { // <-----------------------
return ( // <-----------------------
<Column // <-----------------------
key={columnName ?? columnIndex} // <-----------------------
header={columnName} // <-----------------------
body={(rowData) => { // <-----------------------
const cellData = rowData[columnName]; // <-----------------------
if (cellData == null) { // null or undefined // <-----------------------
return ''; // <-----------------------
} // <-----------------------
switch (typeof cellData) { // <-----------------------
case 'boolean': // <-----------------------
case 'number': // <-----------------------
case 'string': // <-----------------------
return String(cellData); // <-----------------------
default: // <-----------------------
if (cellData instanceof Date) { // <-----------------------
return String(cellData); //TODO: add formatter // <-----------------------
} // <-----------------------
//TODO: add other cases here... // <-----------------------
return ''; // <-----------------------
} // <-----------------------
}} // <-----------------------
/> // <-----------------------
); // <-----------------------
})}
{" "}
</DataTable>
{" "}
</div>
{" "}
<PaginatorComponent
totalItems={this.props.data.length}
itemsPerPage={itemsPerPage}
currentPage={currentPage}
onPageChange={this.handlePageChange}
rowsCountOptions={[3, 5, 10, 20]}
/>
{" "}
</div>
);
}
}
// Export the CustomDataTable component.
export default CustomDataTable;
Columns and rows rendering can be achieved using mapping:
// ...
const columnRenderers = this.props.columnRenderers as any;
const columnKeys = Object.keys(columnRenderers);
// ...
{columnKeys.map((columnKey: string, columnIndex: number) => {
return (
<Column
key={columnKey ?? columnIndex}
header={columnKey}
body={(rowData) => String(rowData[columnKey])}
/>
);
})}
// ...
Hint: change
String(rowData[columnKey])
to proper redering.
Practical example
CustomDataTable
component:
import React, { Component, ReactNode } from "react";
import { DataTable } from "primereact/datatable";
import { Checkbox } from "primereact/checkbox";
import { Column, ColumnProps } from "primereact/column";
import "primereact/resources/themes/mdc-dark-deeppurple/theme.css";
import "primereact/resources/primereact.min.css";
import "primeicons/primeicons.css";
import { PaginatorComponent } from "./paginatorComponent";
import "./customDataTable.css";
// Define the properties that the CustomDataTable component expects as input.
interface DataTableProps {
data: any[]; // Input: The data to display in the table.
checkbox: boolean; // Input: Indicates whether to show checkboxes for row selection.
sortField: string | null; // Input: The field used for sorting.
sortOrder: number; // Input: The sorting order (1 for ascending, -1 for descending).
onSortChange: (field: string, order: number) => void; // Output: Callback for sorting change.
onSelectionChange: (selectedRows: any[], selectAll: boolean) => void; // Output: Callback for selection change.
scrollHeight?: string; // Input: Height for the table with a scrollbar.
scrollWidth?: string; // Input: Width for the table with a scrollbar.
columnRenderers?: Record<string, (cellData: any) => ReactNode>; // Input: Renderers for custom column data.
children?: ReactNode; // Child components, which are the columns of the table.
scrollable?: boolean; // Input: Indicates whether the table should be scrollable.
}
// Define the state structure for the CustomDataTable component.
interface DataTableState {
currentPage: number; // Current page of the table.
selectedRows: any[]; // Selected rows in the table.
dataToDisplay: any[]; // Data to display in the table.
selectAll: boolean; // Indicates whether all rows are selected.
itemsPerPage: number; // Number of items to display per page.
}
// Define the CustomDataTable component.
class CustomDataTable extends Component<DataTableProps, DataTableState> {
// Constructor for the component, initializing state and binding methods.
constructor(props: DataTableProps) {
super(props);
this.state = {
currentPage: 1,
selectedRows: [],
dataToDisplay: this.props.data,
selectAll: false,
itemsPerPage: 3,
};
}
// componentDidUpdate is called when props change, used for sorting updates.
componentDidUpdate(prevProps: DataTableProps, prevState: DataTableState) {
if (
prevProps.data !== this.props.data ||
prevProps.sortField !== this.props.sortField ||
prevProps.sortOrder !== this.props.sortOrder
) {
this.sortData();
}
}
// Callback for changing the current page.
handlePageChange = (newPage: number) => {
this.setState({ currentPage: newPage });
}; // Toggle the selection of all rows in the table.
toggleAllRows = () => {
const { selectAll, dataToDisplay } = this.state;
if (selectAll) {
// If all rows are already selected, clear the selection.
this.setState({ selectedRows: [] });
} else {
// If not all rows are selected, select all of them.
this.setState({ selectedRows: [...dataToDisplay] });
} // Toggle the selectAll flag and trigger the onSelectionChange callback.
this.setState({ selectAll: !selectAll }, () => {
this.props.onSelectionChange(this.state.selectedRows, !selectAll);
});
};
// Toggle the selection of a single row.
toggleRow = (rowData: any) => {
const { selectedRows } = this.state;
const rowIndex = selectedRows.findIndex((row) => row.id === rowData.id);
if (rowIndex === -1) {
// If the row is not selected, add it to the selection.
this.setState(
{ selectedRows: [...selectedRows, rowData], selectAll: false },
() => {
this.props.onSelectionChange(this.state.selectedRows, false);
}
);
} else {
// If the row is already selected, remove it from the selection.
const newSelectedRows = [...selectedRows];
newSelectedRows.splice(rowIndex, 1);
this.setState({ selectedRows: newSelectedRows, selectAll: false }, () => {
this.props.onSelectionChange(newSelectedRows, false);
});
}
};
// Sort the data based on the selected sort field and order.
sortData = () => {
const { sortField, sortOrder } = this.props;
if (sortField) {
// Create a sorted copy of the data based on the sortField and sortOrder.
const sorted = [...this.state.dataToDisplay].sort((a, b) => {
const aValue = a[sortField];
const bValue = b[sortField]; // Determine if the field values are numerical.
const isNumerical = !isNaN(parseFloat(aValue)) && !isNaN(parseFloat(bValue));
let result = 0;
if (isNumerical) {
// If the values are numerical, compare them directly.
result = sortOrder === 1 ? aValue - bValue : bValue - aValue;
} else {
// If the values are not numerical, perform a string-based comparison.
result = sortOrder === 1 ? aValue.localeCompare(bValue) : bValue.localeCompare(aValue);
}
return result;
});
// Update the dataToDisplay state with the sorted data.
this.setState({ dataToDisplay: sorted });
}
};
// Callback for changing the number of items per page.
handleItemsPerPageChange = (itemsPerPage: number) => {
this.setState({ itemsPerPage }, () => {
this.updateDisplayedData();
});
};
// Update the displayed data based on the current page and items per page.
updateDisplayedData = () => {
const { currentPage, itemsPerPage } = this.state;
const startIndex = (currentPage - 1) * itemsPerPage;
const endIndex = startIndex + itemsPerPage;
const dataToDisplayPaginated = this.state.dataToDisplay.slice(
startIndex,
endIndex
);
console.log(dataToDisplayPaginated);
};
// Callback for sorting column data when a column header is clicked.
handleSortClick = (field: string) => {
const { sortField, sortOrder } = this.props;
if (field === sortField) {
this.props.onSortChange(field, sortOrder === 1 ? -1 : 1);
} else {
this.props.onSortChange(field, 1);
}
};
// Lifecycle method called after the component is mounted.
componentDidMount() {
console.log(`Initial Sorting Direction: ${this.props.sortOrder}`);
}
// Render method for the component.
render() {
const columnRenderers = this.props.columnRenderers as any; // <-----------------------
const columnKeys = Object.keys(columnRenderers); // <-----------------------
const {
currentPage,
selectedRows,
dataToDisplay,
selectAll,
itemsPerPage,
} = this.state;
const { checkbox } = this.props; // Calculate the index range for the current page.
const startIndex = (currentPage - 1) * itemsPerPage;
const endIndex = startIndex + itemsPerPage;
const dataToDisplayPaginated = dataToDisplay.slice(startIndex, endIndex);
return (
<div className="custom-data-table-container">
{" "}
<div className="custom-data-table">
{" "}
<DataTable
value={dataToDisplayPaginated}
stripedRows
scrollable
className="custom-data-table-scroll"
>
{" "}
{/* Check if the checkbox option is enabled and add checkbox column if true. */}
{" "}
{checkbox && (
<Column
key="checkbox"
header={
<Checkbox
className="custom-checkbox"
checked={selectAll}
onChange={this.toggleAllRows}
/>
}
body={(rowData) => (
<Checkbox
className="custom-checkbox"
checked={selectedRows.some((row) => row.id === rowData.id)}
onChange={() => this.toggleRow(rowData)}
/>
)}
/>
)}
{" "}
{columnKeys.map((columnKey: string, columnIndex: number) => { // <-----------------------
return ( // <-----------------------
<Column // <-----------------------
key={columnKey ?? columnIndex} // <-----------------------
header={columnKey} // <-----------------------
body={(rowData) => { // <-----------------------
const columnRenderer = columnRenderers[columnKey]; // <-----------------------
return columnRenderer(rowData); // <-----------------------
}} // <-----------------------
/> // <-----------------------
); // <-----------------------
})}
{" "}
</DataTable>
{" "}
</div>
{" "}
<PaginatorComponent
totalItems={this.props.data.length}
itemsPerPage={itemsPerPage}
currentPage={currentPage}
onPageChange={this.handlePageChange}
rowsCountOptions={[3, 5, 10, 20]}
/>
{" "}
</div>
);
}
}
// Export the CustomDataTable component.
export default CustomDataTable;
Example usage:
<CustomDataTable
data={[
{id: 1, name: 'aaa'},
{id: 2, name: 'bbb'},
{id: 3, name: 'ccc'},
{id: 4, name: 'ddd'}
]}
checkbox={true}
sortField="id"
sortOrder={-1}
onSortChange={(field: string, order: number): void => {}}
onSelectionChange={(selectedRows: any[], selectAll: boolean): void => {}}
columnRenderers={{
id: (rowData: any): ReactNode => {
return <>{String(rowData.id)}</>;
},
name: (cellData: any): ReactNode => {
return <>{String(rowData.name)}</>;
}
}}
/>
Example preview: