Get 2025 Templates Mega Bundle!$1000 worth of 19 Bootstrap HTML, Vue & React Templates + 3 Vector Sets for just $99
Get for 99$

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
</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
Here's a how to add some HTML formatting to your comment:
  • <pre></pre> for JS codes block
  • <pre lang="html"></pre> for HTML code block
  • <pre lang="scss"></pre> for SCSS code block
  • <pre lang="php"></pre> for PHP code block
  • <code></code> for single line of code
  • <strong></strong> to make things bold
  • <em></em> to emphasize
  • <ul><li></li></ul>  to make list
  • <ol><li></li></ol>  to make ordered list
  • <h3></h3> to make headings
  • <a></a> for links
  • <img> to paste in an image
  • <blockquote></blockquote> to quote somebody
  • 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) => (
<div
className="cursor-pointer hover:bg-gray-100"
onClick={() => navigate(`/license/${info.row.original.LicenseId}`)}
>
{info.row.original.LicenseName}
</div>
)


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

Regards,
Sean


Text formatting options
Submit
Here's a how to add some HTML formatting to your comment:
  • <pre></pre> for JS codes block
  • <pre lang="html"></pre> for HTML code block
  • <pre lang="scss"></pre> for SCSS code block
  • <pre lang="php"></pre> for PHP code block
  • <code></code> for single line of code
  • <strong></strong> to make things bold
  • <em></em> to emphasize
  • <ul><li></li></ul>  to make list
  • <ol><li></li></ol>  to make ordered list
  • <h3></h3> to make headings
  • <a></a> for links
  • <img> to paste in an image
  • <blockquote></blockquote> to quote somebody
  • happy  :)
  • shocked  :|
  • sad  :(
Text formatting options
Submit
Here's a how to add some HTML formatting to your comment:
  • <pre></pre> for JS codes block
  • <pre lang="html"></pre> for HTML code block
  • <pre lang="scss"></pre> for SCSS code block
  • <pre lang="php"></pre> for PHP code block
  • <code></code> for single line of code
  • <strong></strong> to make things bold
  • <em></em> to emphasize
  • <ul><li></li></ul>  to make list
  • <ol><li></li></ol>  to make ordered list
  • <h3></h3> to make headings
  • <a></a> for links
  • <img> to paste in an image
  • <blockquote></blockquote> to quote somebody
  • happy  :)
  • shocked  :|
  • sad  :(