dmc.MultiSelect as Dash AG Grid custom component

Hey guys,

I am trying to create a multiple choice dropdown for my dash ag grid table, and found dmc.MultiSelect as a good option.

In my dashAgGridComponentFunctions.js file I have the following code:

//dmc select componenet

dagcomponentfuncs.CustomMultiSelect = function (props) {
    const {setData, data} = props;
    const [selectedOptions, setSelectedOptions] = React.useState(Array.isArray(data) ? data : []);

    function onChange(value) {
        setSelectedOptions(value);
        setData(value);
    }

    return React.createElement(
        window.dash_mantine_components.MultiSelect,
        {
            data: ['a', 'b', 'c'],
            value: selectedOptions,
            onChange: onChange,
            placeholder: "Select options",
        }
    );
};

and I reference the component in my dash ag grid table like this:

columnDefs = [
    {
        "headerName": "Options",
        "cellRenderer": "CustomMultiSelect",
    },
]

dash_ag_grid.AgGrid(
                                        id="my-table",
                                        dashGridOptions={
                                            "rowHeight": 120,
                                            "rowSelection": "multiple",
                                            "undoRedoCellEditing": True,
                                            "suppressRowTransform": True,
                                        },
                                        columnDefs=columnDefs,
                                        defaultColDef={
                                            "flex": 1,
                                            "sortable": True,
                                            "filter": True,
                                        },
                                    )

I can see the options, but I cannot choose/select anything. Any idea what am I doing wrong? Thanks!

Hello @kjurukova,

Yes, adding dash components are a little more tricky when working inside the context of the grid.

You need to tie in the setProps to update the data for the cell, I don’t think the onChange does anything because it’s not your typical select.

Basically, use the setProps and then check if the value changes, if so, use setData.

Thank you very much @jinnyzor !!!
Worked like this:

dagcomponentfuncs.CustomMultiSelect = function (props) {
    const {setData, data} = props;
    const [selectedOptions, setSelectedOptions] = React.useState(Array.isArray(data) ? data : []);

    function onChange(value) {
        setSelectedOptions(value);
        setData(value);
    }

    function setProps(value){
        data: value;
    }

    return React.createElement(
        window.dash_mantine_components.MultiSelect,
        {
            data: ['a', 'b', 'c'],
            value: selectedOptions,
            onChange,
            setProps,
            placeholder: "Select options",
        }
    );
};
1 Like

Hello,

I’d like to do the same thing, but I can’t provide the list of possible choices.

Here’s a basic example of an app I can’t get to work :

from dash import Dash, html, Output, Input, callback
import dash_ag_grid as dag
import dash_mantine_components as dmc
import pandas as pd

df = pd.read_csv("https://raw.githubusercontent.com/plotly/datasets/master/wind_dataset.csv")
df.loc[:, 'direction'] = 'S'

app = Dash(__name__)

columnDefs = [
    {"field": "id", "hide": True},
    {'field': 'direction', 'editable': True, "cellRenderer": "CustomMultiSelect",
     'cellEditorParams': {'value': ["N", "S", "E", "W"]}},
{'field': 'strength', 'editable': False},
{'field': 'frequency', 'editable': False},
]

grid = dag.AgGrid(
    id="get-started-example-basic",
    rowData=df.to_dict("records"),
    columnDefs=columnDefs,
)

app.layout = html.Div([grid])

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

The dashAgGridComponentFunctions.js file contains :

var dagcomponentfuncs = window.dashAgGridComponentFunctions = window.dashAgGridComponentFunctions || {};


dagcomponentfuncs.CustomNoRowsOverlay = function (props) {
    return React.createElement(
        'div',
        {
            style: {
                border: '1pt solid grey',
                color: 'grey',
                padding: 10,
                fontSize: props.fontSize
            },
        },
        props.message
    );
};


dagcomponentfuncs.CustomMultiSelect = function (props) {
    const {setData, data} = props;
    const [selectedOptions, setSelectedOptions] = React.useState(Array.isArray(data) ? data : []);

    function onChange(value) {
        setSelectedOptions(value);
        setData(value);
    }

    function setProps(value){
        data: value;
    }

    return React.createElement(
        window.dash_mantine_components.MultiSelect,
        {
            data: ['a', 'b', 'c'],
            value: selectedOptions,
            onChange,
            setProps,
            placeholder: "Select options",
        }
    );
};

Thank you for your help.

Is it possible to have a very simple working example?
Because I’m still stuck.

Thanks

I’ve found the solution.
All I had to do was copy the Select example here:
https://dashaggrid.pythonanywhere.com/components/cell-editor-components
by changing the Select element to MultiSelect and deleting the filterDataOnExactSearchMatch attribute.

3 Likes

Yes. The cellEditor is easier to use than the cellRenderer. The issue was that your component wasn’t showing up because of being contained inside of the cell.

When you allow for the pop up, it adds it above the grid, so it’s no longer contained inside the cell.

Hey @Jocelyn

Could you please share the select example? Seems like to select example was removed :weary:

Hi @kabure

You can find 3 dmc.Select examples here. Note that it currently it uses dmc== 0.12.1

1 Like

Hey @AnnMarieW Thank you so much!

I’ve already understood how it works, and it’s exactly the solution I need… The issues I see are mainly:
1- I need to apply this to the ROWS and not to the COLUMNS;
2 - My list has more than 38k options;

Do you think that is it possible to be applied to my case?

It’s late here now, I will try to implement this tomorrow, but I’m not too confident as I will need to pass the 38k list for each column

Do you know a way that I could load a json file in the .js file? I think that it would avoid the need to set the same list many times