Column Menus
All columns in the Infinite Table have a default menu, which can be customized or hidden altogether.
Customise the menu items
To customize the column menu (for all columns, or for a specific column), use the getColumnMenuItems
prop. This function is called with an array of menu items (which are the default items) and it should the final array of menu items - so you can return the default items as is, or you can adjust the default items to fit your needs.
function getColumnMenuItems(items, { column }) {
if (column.id === 'firstName') {
// you can adjust the default items for a specific column
items.splice(0, 0, {
key: 'firstName',
label: 'First name menu item',
onClick: () => {
console.log('Hey there!');
},
});
}
// or for all columns
items.push({
key: 'hello',
label: 'Hello World',
onClick: () => {
alert('Hello World from column ' + column.id);
},
});
return items;
}
Note
getColumnMenuItems
can return an empty array, in which case, the column menu will not be shown - however, people will still be able to click the menu icon to trigger the column context menu.
If you want to dynamically decide whether a column should show a menu or not, you can use the columns.renderMenuIcon
prop.
In this example, the currency and preferredLanguage columns have a custom icon for triggering the column context menu.
In addition, the preferredLanguage
column has a custom header that shows a button for triggering the column context menu.
import { InfiniteTable, DataSource, InfiniteTablePropColumns, } from '@infinite-table/infinite-react'; import * as React from 'react'; type Developer = { id: number; firstName: string; lastName: string; country: string; city: string; currency: string; preferredLanguage: string; stack: string; canDesign: 'yes' | 'no'; hobby: string; salary: number; age: number; }; const dataSource = () => { return fetch('https://infinite-table.com/.netlify/functions/json-server' + '/developers1k') .then((r) => r.json()) .then((data: Developer[]) => data); }; const columns: InfiniteTablePropColumns<Developer> = { currency: { field: 'currency', // custom menu icon renderMenuIcon: () => <div>🌎</div>, }, preferredLanguage: { field: 'preferredLanguage', defaultWidth: 350, header: ({ columnApi, insideColumnMenu }) => { // if we're inside the column menu with all columns, return only the col name if (insideColumnMenu) { return 'Preferred Language'; } // but for the real column header // return this custom content return ( <> Preferred Language{' '} <button // we need to stop propagation so we don't trigger a sort when this button is clicked onPointerDown={(e) => e.stopPropagation()} onMouseDown={(e) => { // again, stop propagation so the menu is not closed automatically // so we can control it in the line below e.stopPropagation(); columnApi.toggleContextMenu(e.target); }} style={{ border: '1px solid magenta', margin: 2 }} > Toggle menu </button> </> ); }, // custom menu icon renderMenuIcon: () => <div>🌎</div>, }, salary: { field: 'salary', // hide the menu icon renderMenuIcon: false, }, country: { field: 'country', }, id: { field: 'id', defaultWidth: 80, renderMenuIcon: false }, firstName: { field: 'firstName', }, }; export default function ColumnContextMenuItems() { return ( <> <DataSource<Developer> primaryKey="id" data={dataSource}> <InfiniteTable<Developer> columnHeaderHeight={70} columns={columns} getColumnMenuItems={(items, { column }) => { if (column.id === 'firstName') { // you can adjust the default items for a specific column items.splice(0, 0, { key: 'firstName', label: 'First name menu item', onAction: () => { console.log('Hey there!'); }, }); } items.push( { key: 'hello', label: 'Hello World', onAction: () => { alert('Hello World from column ' + column.id); }, }, { key: 'translate', label: 'Translate', menu: { items: [ { key: 'translateToEnglish', label: 'English', onAction: () => { console.log('Translate to English'); }, }, { key: 'translateToFrench', label: 'French', onAction: () => { console.log('Translate to French'); }, }, ], }, }, ); return items; }} /> </DataSource> </>
As you can see in the demo above, you can use getColumnMenuItems
to return the default items (received as the first parameter to the function), or another totally different array. We chose to pass the default items to the function, so you can use them as a starting point and adjust them to your needs.
Each item in the array you return from getColumnMenuItems
should have a key
and a label
property. Additionally, you can specify an onAction
function, which will be called when the user clicks the menu item.
It's also possible to create items with submenus. For this, specify a menu
property in the item, with an items
array. Each item in the items
array should have a key
and a label
property, as you would expect.
function getColumnMenuItems(items, { column }) {
const items = [
{
key: 'translate',
label: 'Translate',
menu: {
items: [
{
key: 'translateToEnglish',
label: 'English',
onAction: () => {
console.log('Translate to English');
},
},
{
key: 'translateToFrench',
label: 'French',
onAction: () => {
console.log('Translate to French');
},
},
],
},
},
];
return items;
}
Custom menu icon
To customize the menu icon, use the columns.renderMenuIcon
prop. This prop can be a boolean or a function that returns a ReactNode
.
const columns = {
name: {
field: 'firstName',
renderMenuIcon: () => <div>🌎</div>,
},
salary: {
field: 'salary',
renderMenuIcon: false,
},
};
Note
For a custom menu icon 🌠 you don't have to hook up the mousedown
/click
in order to show or hide the menu - all this is done for you - just render your custom ReactNode
and you're good to go.