Search code examples
reactjscomponents

Modifying React Data Table Extension Component


I want to modify the react data table extension component with the below functionalities but I'm stuck and unable to modify it.

  1. Change auto filter to event based filter set to button onClick
  2. Change default search icon to bootstrap button
  3. Use the export and print button (currently set the ... Data to the data-table-extension as per documentation but it is only displays the data in the data table but I'm unable to use print and export functionality).

I'm currently using react 18

I have tried to put data in the react data table component, when I do so the print and export functionality works perfectly fine but no data gets display in the data table.

My code is as under:



import DataTable from "react-data-table-component"; 

 import { tableCustomStyles } from "../../utils/CommonFunctions"; 

 import DataTableExtensions from "react-data-table-component-extensions"; 


export default function UsersPage() {

  const dataTableColumns = [

     { 

       name: "#", 

       selector: (row, index) => `${index + 1}`, 

       sortable: false, 

       width: "50px", 

     }, 

     { 

       name: "Last Name", 

       selector: (row) => row.lastName, 

       sortable: true, 

       width: "150px", 

     }, 

     { 

       name: "First Name", 

       selector: (row) => row.firstName, 

       sortable: true, 

       width: "150px", 

     }, 

     { 

       name: "Role(s)", 

       selector: (row) => row?.roles?.map((role) => role?.name).join(", "), 

       sortable: true, 

       width: "230px", 

     }, 

     { 

       name: "Department(s)", 

       selector: (row) => 

         row?.departments?.map((department) => department?.name).join(", "), 

       sortable: true, 

       width: "230px", 

     }, 

     { 

       name: "Location(s)", 

       selector: (row) => 

         row?.locations?.map((location) => location?.name).join(", "), 

       sortable: true, 

       width: "230px", 

     }, 

     { 

       name: "Status", 

       selector: (row) => row?.status, 

       sortable: true, 

       width: "100px", 

     }, 

     { 

       name: "Option(s)", 

       cell: (row) => ( 

         <> 

           <Dropdown> 

             <Dropdown.Toggle variant='link' id='dropdown-basic'> 

               <VerticalDots style={{ height: 20 }} /> 

             </Dropdown.Toggle> 

  

             <Dropdown.Menu> 

               <Dropdown.Item onClick={() => handleViewFullProfile(row)}> 

                 View Full Profile 

               </Dropdown.Item> 

               <Dropdown.Item onClick={() => handleResetPassword(row)}> 

                 Reset Password 

               </Dropdown.Item> 

               <Dropdown.Item onClick={() => handleUserStatus(row)}> 

                 {row.status === "Active" ? "Deactivate" : "Activate"} User 

               </Dropdown.Item> 

               <Dropdown.Item onClick={() => handleOptionClick(row)}> 

                 Other Option 

               </Dropdown.Item> 

             </Dropdown.Menu> 

           </Dropdown> 

         </> 

       ), 

       ignoreRowClick: true, 

       allowOverflow: true, 

       button: true, 

       sortable: false, 

       width: "100px", 

     }, 

   ]; 

   const tableData = { 

     columns: dataTableColumns, 

     data: users, 




 
return (
<div>
          <a 

             className='btn btn-primary' 

             to='/admin/administer/new-user' 

             onClick={handleNavigation} 

           > 

             + Add User 

           </a> 

           <DataTableExtensions 

             {...tableData} 

             export={true} 

             print={true} 

             extensions={extensions} 

           > 

             <DataTable 

               // columns={dataTableColumns} 

               // data={users} 

               noHeader 

               defaultSortField='lastName' 

               defaultSortAsc={false} 

               customStyles={tableCustomStyles} 

               pagination 

               responsive='true' 

               highlightOnHover 

             /> 

           </DataTableExtensions> 

         </div>
)}


Solution

  • I finally managed to resolve my concerns... And I learned that currently react-data-table-component and extension don't give much flexibility when it comes to updating the component to your specific requirements. And the last update of the component was one year old, with total downloads within 2-2.5k

    So I used my custom input and search button and filtered the data being received through back end and to fix the issues of export and print I gave data as string in the selector instead of (row) => row.name method

    Also one more challenge that I was facing was that data table was displaying conent that was growing outside the container giving a horizontal scroll option which was not required so I used wrap property for columns with more text and gave fixed width to columns with less text to resolve this issue.

    My updated Code is as under:

    import DataTable from "react-data-table-component";
    import {
      searchFunctionality,
      tableCustomStyles,
    } from "../../utils/CommonFunctions";
    import DataTableExtensions from "react-data-table-component-extensions";
    import "react-data-table-component-extensions/dist/index.css";
    
    export default function RolesData() {
      const [roles, setRoles] = useState([]);
      const [filteredValue, setFilteredValue] = useState("");
      const [finalFilteredValue, setFinalFilteredValue] = useState("");
      const [filteredData, setFilteredData] = useState([]);
    
    useEffect(() => {
        const filteredData = searchFunctionality(
          roles,
          dataTableColumns,
          finalFilteredValue
        );
        setFilteredData(filteredData);
      }, [roles, finalFilteredValue]);
    
      const callGetRolesApi = async () => {
        try {
          let res = await getRoles();
          const { message, data, status } = res;
    
          console.log(res);
          if (status == clientSideStatus.success) {
            data.forEach((user, index) => {
              user.serial = index + 1;
              user.refinedRoles = user?.roles?.map((role) => role?.name).join(", ");  });
    
            setRoles(data);
            setFilteredData(data);
            console.log(data);
          } else {
            toast.error(message);
          }
        } catch (err) {
          console.error(err);
          toast.error(clientDefinedMessages.rolesError);
        }
      };
    
    const dataTableColumns = [
        {
          name: "#",
          selector: "serial",
          sortable: false,
          width: "50px",
        },
        {
          name: "Role Name",
          selector: "name",
          sortable: true,
          // width: "140px",
          wrap: true,
        },
        {
          name: "Type of Role",
          selector: "roleTypeName",
          sortable: true,
          // width: "140px",
          wrap: true,
        },
        {
          name: "Status",
          selector: "status",
          sortable: true,
          width: "140px",
          wrap: true,
        },
        {
          name: "Member(s)",
          selector: "usersCount",
          style: { "text-decoration": "link", color: "blue" },
          sortable: false,
          // width: "140px",
          wrap: true,
          ignoreRowClick: true,
          allowOverflow: true,
          button: true,
          width: "150px",
          cell: (row) => (
            <>
              <button
                type='button'
                className='btn btn-link '
                onClick={() => handleMembersCountNavigation(row)}
              >
                {row.usersCount}
              </button>
            </>
          ),
        },
        {
          name: "Option(s)",
          cell: (row) => (
            <>
              <Dropdown>
                <Dropdown.Toggle
                  variant='fade-primary'
                  id={`dropdown-${row?.role?.id}`}
                  className='d-flex'
                >
                  <VerticalDots style={{ height: 20 }} />
                </Dropdown.Toggle>
                <Dropdown.Menu>
                  <Dropdown.Item
                    onClick={() => handleViewDetailsNavigation(row?.id)}
                  >
                    View Details
                  </Dropdown.Item>
                </Dropdown.Menu>
              </Dropdown>
            </>
          ),
          sortable: false,
          // width: "140px",
          wrap: true,
          ignoreRowClick: true,
          allowOverflow: true,
          button: true,
          width: "150px",
        },
      ];
    
      const tableData = {
        columns: dataTableColumns,
        data: filteredData,
      };
    
    return (
        <>
          {!roles ? (
            <div className='d-flex justify-content-center p-3'>Loading...</div>
          ) : (
            <div
              className='d-flex align-intems-center flex-wrap col-md-6 col-lg-12'
              style={{ width: "100%", justifyContent: "center" }}
            >
              <a
                className='btn btn-primary d-flex align-items-center'
                to='/admin/administer/new-user'
                onClick={handleNavigation}
              >
                + Add User
              </a>
              <div
                className='input-group ms-auto'
                style={{ width: 340, display: "inline-flex" }}
              >
                <input
                  type='text'
                  className='form-control'
                  placeholder='Search Users'
                  value={filteredValue}
                  aria-describedby='button-addon2'
                  onChange={(event) => setFilteredValue(event.target.value)}
                />
                <button
                  className='btn btn-outline-primary'
                  type='button'
                  id='button-addon2'
                  onClick={() => setFinalFilteredValue(filteredValue)}
                >
                  Go
                </button>
                <button
                  type='button'
                  className='btn btn-outline-primary'
                  aria-label='Clear'
                  onClick={() => {
                    setFilteredValue("");
                    setFinalFilteredValue("");
                  }}
                >
                  Clear
                </button>
              </div>
    
              <DataTableExtensions {...tableData} filter={false}>
                <DataTable
                  columns={dataTableColumns}
                  data={roles}
                  noHeader
                  // defaultSortField='lastName'
                  defaultSortAsc={false}
                  customStyles={tableCustomStyles}
                  pagination
                  highlightOnHover
                />
              </DataTableExtensions>
            </div>
          )}
        </>
      );
    
    
    

    The common functions created for the styling and filtering data are as under:

    export const tableCustomStyles = {
      headCells: {
        style: {
          fontSize: "14px",
          fontWeight: "bold",
          paddingLeft: "8px",
          justifyContent: "left",
          color: "#1e78fd",
        },
      },
      cells: {
        style: {
          fontSize: "14px",
          paddingLeft: "8px",
          justifyContent: "left",
          whiteSpace: "normal",
        },
      },
      container: {
        display: "flex",
        justifyContent: "flex-end",
        marginBottom: "20px",
        // Add any other custom styles you need
      },
      filterInput: {
        marginRight: "10px",
        // Add any other custom styles for the filter input
      },
    };
    
    export const searchFunctionality = (data, dataTableColumns, filteredValue) => {
      let data1 = data?.filter((dat) => {
        if (filteredValue !== "") {
          for (let i = 0; i < dataTableColumns.length; i++) {
            if (dataTableColumns[i]?.selector) {
              if (
                dat[dataTableColumns[i]?.selector]
                  ?.toString()
                  ?.toLowerCase()
                  ?.includes(filteredValue?.toLowerCase())
              )
                return true;
            }
          }
          return false;
        }
        return true;
      });
      data1?.forEach((user, index) => {
        user.serial = index + 1;
      });
      return data1;
    };
    ````[![enter image description here][1]][1]
    
    
      [1]: https://i.sstatic.net/P1JNH.png