Super Sale Limited Time 50% OFF for All-Access Plans
Save 50% Now

On click for data grid in metronic 9 ?

Below is the code I am using for generating a table.

I need to make each row clickable and navigate to different page. How to do that?

import { useMemo, useState, useEffect } from 'react'; import { useNavigate, useLocation } from 'react-router-dom'; import { DataGrid, KeenIcon, TDataGridRequestParams } from '@/components'; import { ColumnDef } from '@tanstack/react-table'; import axios from 'axios'; import { FetchLicensesResponse, LicenseModel } from '@/providers'; import { enqueueSnackbar } from 'notistack'; import { Container } from '@/components/container'; import { LicenseViewModal } from './LicenseViewModal';

const LicenseTable = () => { const navigate = useNavigate(); const location = useLocation();

const [viewLicenseModal, setViewLicenseModal] = useState(false);
const [selectedLicenseId, setSelectedLicenseId] = useState("");

useEffect(() => {
    const queryParams = new URLSearchParams(location.search);
    const licenseId = queryParams.get('licenseId');
    const modalOpen = queryParams.get('modal') === 'true';

    if (modalOpen && licenseId) {
        setSelectedLicenseId(licenseId);
        setViewLicenseModal(true);
    }
}, [location.search]);

const handleSettingsModalClose = () => {
    setViewLicenseModal(false);
    navigate(location.pathname);
};

const handleLicenseViewAction = (licenseId: string) => {
    navigate(`/license/${licenseId}`)
    // navigate(`?modal=true&licenseId=${licenseId}`);
};

const columns = useMemo<ColumnDef<LicenseModel>[]>(
    () => [
        {
            accessorFn: (row) => row,
            id: 'licenseName',
            header: () => 'Name',
            cell: (info) => info.row.original.LicenseName,
            meta: { headerClassName: 'min-w-[180px]' },
        },
        {
            accessorFn: (row) => row,
            id: 'licenseType',
            header: () => <div className='text-center'>Type</div>,
            cell: (info) => <div className='text-center'>{info.row.original.LicenseType}</div>,
            meta: { headerClassName: 'min-w-20' },
        },
        {
            accessorFn: (row) => row,
            id: 'organisation',
            header: () => 'Organisation',
            cell: (info) =>
                info.row.original.Organisation || <div>---</div>,
            meta: { headerClassName: 'min-w-[180px]' },
        },
        {
            accessorFn: (row) => row,
            id: 'unit',
            header: () => 'Unit',
            cell: (info) =>
                info.row.original.Unit || <div>---</div>,
            meta: { headerClassName: 'min-w-[180px]' },
        },
        {
            accessorFn: (row) => row,
            id: 'revoked',
            header: () => <div className='text-center'>Revoked</div>,
            cell: (info) =>
                <div className='text-center'>
                    <span className={`badge badge-sm ${info.row.original.Revoked ? 'badge-danger' : 'badge-success'} badge-outline`}>
                        {info.row.original.Revoked ? <KeenIcon icon="check" /> : <KeenIcon icon="cross" />}
                    </span>
                </div>,
            meta: { headerClassName: 'min-w-10 text-center' },
        },
        {
            accessorFn: (row) => row,
            id: 'action',
            header: () => <div className='text-center'>Action</div>,
            cell: (info) => (
                <div className="flex flex-wrap gap-5 justify-center">
                    <div className="flex">
                        <button
                            className="btn btn-sm btn-primary btn-outline"
                            data-toggle="tooltip"
                            title="View details"
                            onClick={() => handleLicenseViewAction(info.row.original.LicenseId)}
                        >
                            <KeenIcon icon="eye" />
                        </button>
                    </div>
                    <div className="flex">
                        <button
                            className="btn btn-sm btn-danger btn-outline"
                            data-toggle="tooltip"
                            title="Deactivate"
                        >
                            <KeenIcon icon="shield-slash" />
                        </button>
                    </div>
                </div>
            ),
            meta: { headerClassName: 'min-w-5 text-center' },
        },
    ],
    []
);

const onFetchData = async (params: TDataGridRequestParams) => {
    try {
        const offset = params.pageIndex * params.pageSize;

        const response = await axios.post<FetchLicensesResponse>(
            `${import.meta.env.VITE_APP_API_URL}/license/fetch`,
            { maxEntries: params.pageSize, offset }
        );

        return {
            data: response.data.licenses || [],
            totalCount: 30,
            offset,
            nextOffset: offset + params.pageSize,
        };
    } catch (error) {
        console.error('Failed to fetch data:', error);
        enqueueSnackbar('An error occurred while fetching data. Please try again later', {
            variant: 'solid',
            state: 'danger',
        });

        return {
            data: [],
            totalCount: 0,
            offset: 0,
        };
    }
};

return (
    <>
        <div className="card card-grid min-w-full">
            <div className="card-header flex-wrap gap-2">
                <h3 className="card-title font-medium text-sm">Your Licenses</h3>
            </div>
            <div className="card-body">
                <DataGrid
                    layout={{ card: true, cellBorder: false }}
                    columns={columns}
                    serverSide={true}
                    onFetchData={onFetchData}
                    rowSelection={false}
                    pagination={{ size: 10 }}
                />
            </div>
        </div>
        <Container>
            <LicenseViewModal
                open={viewLicenseModal}
                onOpenChange={handleSettingsModalClose}
                licenseId={selectedLicenseId}
            />
        </Container>
    </>
);

};

export { LicenseTable };

Text formatting options
Submit
Click any option to insert into your comment. Select text first to wrap it.
  • **text** to make things bold
  • *text* to emphasize
  • ### Heading to make headings
  • [link text](url) for links
  • ![alt text](image-url) to paste in an image
  • - item to make a list
  • 1. item to make an ordered list
  • > quote to quote somebody
  • `code` for single line of code
  • ```js ... ``` for JS code block
  • ```html ... ``` for HTML code block
  • ```scss ... ``` for SCSS code block
  • ```php ... ``` for PHP code block
  • --- for a horizontal rule
  • happy  :)
  • shocked  :|
  • sad  :(

Replies (3)


I would like to make entire row clickable and not just one cell. Yes, will use router link to navigate to internal page.



Hi,

We will add this option in the next update.

You can implement it now by modifying src/components/data-grid/DataGrid.tsx and add onRowClick prop.


export interface TDataGridProps<TData extends object> {
onRowClick?: (row: TData) => void;
}


In src/components/data-grid/DataGridTable.tsx add the row click handle:


{table.getRowModel().rows.length ? (
table.getRowModel().rows.map((row: Row<TData>) => (
<tr
key={row.id}
data-state={row.getIsSelected() ? "selected" : undefined}
onClick={() => props.onRowClick && props.onRowClick(row.original)}
className={cn(
"border-b hover:bg-muted/30 data-[state=selected]:bg-muted/50",
cellBorder && "[&_>:last-child]:border-e-0"
)}
>
...
</tr>
))


Please give a try and let us know the result.

Regards,
Sean


Hi,

Could you please confirm if you want to make an entire row click or a button click inside a cell of a row to navigate to a new page? Will you use the Router link to navigate to an internal page?

You can try to use this in the columns config:

cell: (info) => (
  
navigate(`/license/${info.row.original.LicenseId}`)} > {info.row.original.LicenseName}
)

Please make sure you are using the last v9.1.2 version of Metronic Tailwind React.

Regards, Sean

Text formatting options
Submit
Click any option to insert into your comment. Select text first to wrap it.
  • **text** to make things bold
  • *text* to emphasize
  • ### Heading to make headings
  • [link text](url) for links
  • ![alt text](image-url) to paste in an image
  • - item to make a list
  • 1. item to make an ordered list
  • > quote to quote somebody
  • `code` for single line of code
  • ```js ... ``` for JS code block
  • ```html ... ``` for HTML code block
  • ```scss ... ``` for SCSS code block
  • ```php ... ``` for PHP code block
  • --- for a horizontal rule
  • happy  :)
  • shocked  :|
  • sad  :(
Text formatting options
Submit
Click any option to insert into your comment. Select text first to wrap it.
  • **text** to make things bold
  • *text* to emphasize
  • ### Heading to make headings
  • [link text](url) for links
  • ![alt text](image-url) to paste in an image
  • - item to make a list
  • 1. item to make an ordered list
  • > quote to quote somebody
  • `code` for single line of code
  • ```js ... ``` for JS code block
  • ```html ... ``` for HTML code block
  • ```scss ... ``` for SCSS code block
  • ```php ... ``` for PHP code block
  • --- for a horizontal rule
  • happy  :)
  • shocked  :|
  • sad  :(