Context Menu in Dash AG Grid

@LethalNote and @smalgotrader

:tada: Dash AG Grid 2.4.0 is now available

It’s now possible to customize the context menu (An AG Grid Enterprise feature). Here are 2 examples.

1. Customize the Context Menu

This is a Dash version of an example in the AG Grid docs.

ag-grid-context

import dash_ag_grid as dag
from dash import Dash, html
import pandas as pd

app = Dash(__name__)


df = pd.read_csv(
    "https://raw.githubusercontent.com/plotly/datasets/master/ag-grid/olympic-winners.csv"
)

columnDefs = [
    {"field": i} for i in ["country", "year", "athlete", "sport", "total"]
]

app.layout = html.Div(
    [
        dag.AgGrid(
            columnDefs=columnDefs,
            rowData=df.to_dict("records"),
            dashGridOptions={
                "allowContextMenuWithControlKey": True,
                "getContextMenuItems" :{"function": "getContextMenuItems(params)"}
            },
            defaultColDef=dict(
                resizable=True,
                filter=True,
                sortable=True,
            ),
            id="grid-context",
            enableEnterpriseModules=True,

        ),
    ]
)


if __name__ == "__main__":
    app.run(debug=True)


Add the following to the dashAgGridFunctions.js file in the assets folder

var dagfuncs = (window.dashAgGridFunctions = window.dashAgGridFunctions || {});
dagfuncs.getContextMenuItems = (params) => {

    function createFlagImg(flag) {
      return (
        '<img border="0" width="15" height="10" src="https://flags.fmcdn.net/data/flags/mini/' +
        flag +
        '.png"/>'
      );
    }

    var result = [
      {
        // custom item
        name: 'Alert ' + params.value,
        action: () => {
          window.alert('Alerting about ' + params.value);
        },
        cssClasses: ['redFont', 'bold'],
      },
      {
        // custom item
        name: 'Always Disabled',
        disabled: true,
        tooltip:
          'Very long tooltip, did I mention that I am very long, well I am! Long!  Very Long!',
      },
      {
        name: 'Country',
        subMenu: [
          {
            name: 'Ireland',
            action: () => {
              console.log('Ireland was pressed');
            },
            icon: createFlagImg('ie'),
          },
          {
            name: 'UK',
            action: () => {
              console.log('UK was pressed');
            },
            icon: createFlagImg('gb'),
          },
          {
            name: 'France',
            action: () => {
              console.log('France was pressed');
            },
            icon: createFlagImg('fr'),
          },
        ],
      },
      {
        name: 'Person',
        subMenu: [
          {
            name: 'Niall',
            action: () => {
              console.log('Niall was pressed');
            },
          },
          {
            name: 'Sean',
            action: () => {
              console.log('Sean was pressed');
            },
          },
          {
            name: 'John',
            action: () => {
              console.log('John was pressed');
            },
          },
          {
            name: 'Alberto',
            action: () => {
              console.log('Alberto was pressed');
            },
          },
          {
            name: 'Tony',
            action: () => {
              console.log('Tony was pressed');
            },
          },
          {
            name: 'Andrew',
            action: () => {
              console.log('Andrew was pressed');
            },
          },
          {
            name: 'Kev',
            action: () => {
              console.log('Kev was pressed');
            },
          },
          {
            name: 'Will',
            action: () => {
              console.log('Will was pressed');
            },
          },
          {
            name: 'Armaan',
            action: () => {
              console.log('Armaan was pressed');
            },
          },
        ],
      },
      'separator',
      {
        // custom item
        name: 'Windows',
        shortcut: 'Alt + W',
        action: () => {
          console.log('Windows Item Selected');
        },
        icon:
          '<img src="https://www.ag-grid.com/example-assets/skills/windows.png" />',
      },
      {
        // custom item
        name: 'Mac',
        shortcut: 'Alt + M',
        action: () => {
          console.log('Mac Item Selected');
        },
        icon:
          '<img src="https://www.ag-grid.com/example-assets/skills/mac.png"/>',
      },
      'separator',
      {
        // custom item
        name: 'Checked',
        checked: true,
        action: () => {
          console.log('Checked Selected');
        },
        icon:
          '<img src="https://www.ag-grid.com/example-assets/skills/mac.png"/>',
      },
      'copy',
      'separator',
      'chartRange',
    ];
    return result;
  };

2. Custom Context Menu with Dash Callbacks

Shows how how to add custom features to the context menu such as:

  • Accessing the AG Grid API – the example clears all the filters
  • Custom item - open a new tab with a link created from cell data
  • Trigger a Dash Callback

ag-grid-context-callback

import dash_ag_grid as dag
from dash import Dash, html, callback, Input, Output, State
import pandas as pd
import  dash_bootstrap_components as dbc

app = Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP, dbc.icons.FONT_AWESOME])


df = pd.read_csv(
    "https://raw.githubusercontent.com/plotly/datasets/master/ag-grid/olympic-winners.csv"
)

columnDefs = [
    {"field": i} for i in ["country", "year", "athlete", "sport", "total"]
]

app.layout = html.Div(
    [
        html.Button(id="stop", style={"display": "none"}),
        dag.AgGrid(
            columnDefs=columnDefs,
            rowData=df.to_dict("records"),
            dashGridOptions={
                "allowContextMenuWithControlKey": True,
                "getContextMenuItems" :{"function": "getContextMenuItemsCallback(params)"}
            },
            defaultColDef=dict(
                resizable=True,
                filter=True,
                sortable=True,
            ),
            id="grid-context",
            enableEnterpriseModules=True,
        ),
        html.Div(id="output")
    ]
)

@callback(
    Output("output", "children"),
    Input("stop", "n_clicks"),
)
def update(n):
    return f"Stop clicked {n} times."


if __name__ == "__main__":
    app.run(debug=True)

Add the following to the dashAgGridFunctions.js file in the assets folder

var dagfuncs = (window.dashAgGridFunctions = window.dashAgGridFunctions || {});

dagfuncs.getContextMenuItemsCallback = (params) => {
    var result = [
      {
        // access grid's API
        name: 'Clear All Filters',
        action: () => {
          params.api.setFilterModel(null);
        },
        icon: '<i class="fa-solid  fa-square-minus" />'
      },
      {
        // custom item
        name: 'Look up ' + params.value,
        action: () => {
          window.open("https://en.wikipedia.org/wiki/" + params.value, '_blank').focus();
        },
        icon: '<i class="fa-solid  fa-magnifying-glass" />'
      },
       {
        // trigger a callback
        name: 'Stop process',
        action: () => {
          const stopBtn = document.getElementById("stop");          
          stopBtn.click();
        },
        icon: '<i class="fa-solid  fa-stop" />'
      },
      'copy',
      'separator',
      'chartRange',
    ];
    return result;
  };



dag-docs

4 Likes