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 getColumContextMenuItems 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.

customizing column menu
function getColumnContextMenuItems(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

getColumnContextMenuItems 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.

Custom column menu items and custom menu icon

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.

View Mode
Fork
import {
  InfiniteTable,
  DataSource,
  InfiniteTableColumnGroup,
  InfiniteTablePropGetColumnContextMenuItems,
} from '@infinite-table/infinite-react';
import type { 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',
  },
};

const getColumContextMenuItems: InfiniteTablePropGetColumnContextMenuItems<
  Developer
> = (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;
};

export default function ColumnContextMenuItems() {
  return (
    <>
      <DataSource<Developer> primaryKey="id" data={dataSource}>
        <InfiniteTable<Developer>
          columnHeaderHeight={70}
          columns={columns}
          getColumContextMenuItems={getColumContextMenuItems}
        />
      </DataSource>
    </>

As you can see in the demo above, you can use getColumnContextMenuItems 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 getColumnContextMenuItems 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.

Menu items with submenus

function getColumnContextMenuItems(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.

custom menu icon
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.