Inserting TagsInput from Dash Mantine Components into an AG Grid as cell editor

Hello dear dash / plotly community,

I’ve been trying to create a dashboard with Dash and want to be using Dash Mantine Components “TagsInput” widget as a cellEditor. As a component itself I can make it run.
Inserting it into dashAgGridComponentFunction.js doesn’t seem to work for me.

Has anyone make it work?

Hello @justvietvietplotly,

I’m actually going to tackle this today myself, it should be straightforward though.

Are you using the namespace properly?

What version of dmc?

1 Like

Hey @jinnyzor,

thanks for the quick reply. I was already googling a lot and eventually downgraded to dmc=0.12.0.

In my .py-file I inserted

dash._dash_renderer._set_react_version(‘16.14.0’)

in order to use ReactDOM.render(), which is not available with the newest react version anymore!

I’m still trying, if I solved it or have any updates, I’ll post.

Cheers!

You only need to mess with the react version if you are trying to use 18.

What does your js look like?

Heyyah!

I’m basically refering to

// renders component into the editor element
    ReactDOM.render(React.createElement(window.dash_mantine_components.Select, {
        data: params.options, value: params.value, ref: this.ref, setProps, style: {width: params.column.actualWidth},
        className: 'dbc',
        clearable: true,
        searchable: true,
        creatable: true
    }), this.eInput)

My whole js looks almost equal.

Instead of the dash_mantine_components.Select I’m inserting dash_mantine_components.TagsInput and I’m also not supress

Now I’m trying to customize the event which is happening when replacing .Select and clicking the cell, but I’m a bit lost and just keep on googling in order to understand how to make it work!

Edit: Oh I see! TagsInput is not defined as Select is in dash_mantine_components!

1 Like

Okay, update:

So apparently TagsInput got introduced into dmc==0.14.3, which i upgraded it to.
The component is now available in window.dash_mantine_components but I’m still at lost how to make it work like a widget in the DASH AG Grid cell.

Do you have any starting points / ideas, I could look at?

Are you using it as a cell editor, or as a cell renderer?

Can you post some code for how you are trying to make it work?

DMC 0.14 uses Mantine v 7 which made it so every component needs to have the MantineProvider in the tree, this makes it a little more tricky as the editor is rendering the flow outside of the provider.

Hello there!
Right now I’m trying to combine both, to have the editor pop out and behave like the TagsInput from dmc (having proposals etc) and have tags being shown in the column.

But just as you wrote it, it makes more sense to break it down easier. Today I’ll try to make it work as cell editor and just render it as a concatenated string. So I’ll be trying to use a value formatter instead of a cell renderer today.

Here is the JS i’m having so far. It doesnt work yet, but I hope I get one step closer today. :smiley:

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


dagfuncs.TagsInputEditor = class {
    // gets called once before the renderer is used
    init(params) {
        // create the cell
        this.params = params;
        this.eInput = document.createElement('input');
        this.eInput.value = params.value;
        this.eInput.style.height = 'var(--ag-row-height)';
        this.eInput.style.width = '100%';
        this.eInput.classList.add('mantine-TagsInput-input');
        this.eInput.placeholder =  params.placeholder || "";
        this.eInput.name = params.name;


        if (window.dash_mantine_components.TagsInput === undefined) {
            console.log('Dash Mantine Components TagsInput not found');
            return;
        } else {
            console.log('Dash Mantine Components TagsInput found');
        }

        let tagsInputElement = React.createElement(window.dash_mantine_components.TagsInput, {
                placeholder: "Enter tags...",
                clearable: true,
                searchable: true,
                creatable: true,
            });
        if (tagsInputElement === undefined) {
            console.log('React.createElement failed');
        } else {
            console.log('React.createElement success');
        }

        console.log(tagsInputElement);
    }

    // gets called once when grid ready to insert the element
    getGui() {
        return this.eInput;
    }


    // focus and select can be done after the gui is attached
    afterGuiAttached() {
        this.eInput.focus();
        this.eInput.select();
    }

    // returns the new value after editing
    getValue() {
        return this.value;
    }

    // any cleanup we need to be done here
    destroy() {
        // sets focus back to the grid's previously active cell
    }

    isPopup() {
        return false;
    }
};

dagcomponentfuncs.Tags = function (props) {
    if (props.value == 'Placeholder') {
        backgroundColor = '#d8f0d3';
    } else if (props.value == 'Tags') {
        backgroundColor = '#f5cccc';
    } else {
        backgroundColor = '#fffec8';
    }
    return React.createElement(
        'div',
        {
            style: {
                width: '100%',
                height: '100%',
                padding: '5px',
                display: 'flex',
                justifyContent: 'left',
                alignItems: 'center',
            },
        },
        React.createElement(
            'div',
            {
                style: {
                    backgroundColor: backgroundColor,
                    borderRadius: '15px',
                    padding: '5px',
                    color: 'black',
                },
            },
            props.value
        )
    );
};

So the component exists, I just need to return it somehow for my .py dash app to recognize it.

This is the dummy .py file:

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

dash._dash_renderer._set_react_version('18.2.0')
app = Dash(__name__)


df = pd.DataFrame(
    {
        "customTags": [str(i) for i in range(4)],
        "tryOut": ["Placeholder" for  i in range(4)],

    }
)

columnDefs = [
    {"field": "customTags",},
    
    {
        "field": "tryOut",
        "cellEditor": {"function": "TagsInputEditor"},
        "cellEditorParams" : {"placeholder": "Enter some tags"},
        "cellEditorPopup": True,
        "cellRenderer": "Tags",
       
    }
]

defaultColDef = {
    "resizable": True,
    "sortable": True,
    "minWidth": 100,
    "editable": True,
}


app.layout = dmc.MantineProvider(children=[html.Div(
    [
        dag.AgGrid(
            id="cell-editor-dmc-grid",
            columnDefs=columnDefs,
            rowData=df.to_dict("records"),
            columnSize="responsiveSizeToFit",
            defaultColDef=defaultColDef,
        ),
        html.Div(id="cell-editor-dmc-output"),
        html.Div(
   
)

    ],
    style={"margin": 20},
), 
 
        dmc.TagsInput(
            label="Select frameworks",
            placeholder="Select all you like!",
            id="framework-tags-input",
            value=["ng", "vue"],
            w=400,
            mb=10,
        ),
        dmc.Text(id="tags-input-value"),
    ])


@app.callback(
    Output("cell-editor-dmc-output", "children"),
    Input("cell-editor-dmc-grid", "cellValueChanged"),
)
def selected(changed):
    return f"You have selected {changed}"


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

Okay, we’re getting there.
I threw out the dash mantine component, since I didn’t understand how to make it work (yet) and used the autocomplete module from jquery (as shown in the datepicker example).

js:

 $(this.eInput).autocomplete({
            source: ['c++', 'java', 'php', 'coldfusion', 'javascript', 'asp', 'ruby'],
        });

dash.py:

app = Dash(__name__, external_scripts=["https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.1/jquery.min.js", "https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js",], external_stylesheets=["https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.css"],)

Right now pressing into the cell resets the value and gives me an “undefined”-string back and resets the already given input value, but at least I start to see suggestions already! :smile:

Now Im working on making it more user-friendly. Allowing multiple selections (same values are allowed), when pressing into the cell, popping up the tag-suggestions window etc.

If you have ideas to input the widget (TagsInput) id be happy!

Has anyone gotten anywhere with getting TagsInput object working in an ag grid?