Skip to content

Rte expose editor#666

Merged
AnnMarieW merged 11 commits intosnehilvj:masterfrom
AnnMarieW:rte-expose-editor
Nov 6, 2025
Merged

Rte expose editor#666
AnnMarieW merged 11 commits intosnehilvj:masterfrom
AnnMarieW:rte-expose-editor

Conversation

@AnnMarieW
Copy link
Copy Markdown
Collaborator

This PR exposes the RichTextEditor editor instance using dash_mantine_components.getEditor(id) . This gives access to all the editor commands in the Tiptap API https://tiptap.dev/docs/editor/api/commands

Note - the test can be combined with #665 when it's merged.

Here's a cool use-case that can be used in the docs - a character and word counter for the content:

import dash_mantine_components as dmc
from dash import Dash, Input, Output

app=Dash()
app.layout = dmc.MantineProvider([
    dmc.RichTextEditor(id="editor", html=""),
    dmc.Button("Get Stats", id="btn-stats", n_clicks=0),
    dmc.Box(id="stats"),
])

app.clientside_callback(
    """
    function(n_clicks) {
        if (n_clicks > 0) {
            const editor = dash_mantine_components.getEditor('editor');
            if (editor) {
                const text = editor.getText();
                const chars = text.length;
                const words = text.split(/\\s+/).filter(Boolean).length;
                return `Characters: ${chars} | Words: ${words}`;
            }
        }
        return dash_clientside.no_update;
    }
    """,
    Output("stats", "children"),
    Input("btn-stats", "n_clicks"),
)


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

Comment on lines +232 to +242
if (!(window as any).dash_mantine_components) {
(window as any).dash_mantine_components = {};
}
if (!(window as any).dash_mantine_components._editorInstances) {
(window as any).dash_mantine_components._editorInstances = {};
}
if (!(window as any).dash_mantine_components.getEditor) {
(window as any).dash_mantine_components.getEditor = function(id: string) {
return (window as any).dash_mantine_components._editorInstances[id];
};
}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it necessary to create these inside the editor component? Feels like you could create and export the getEditor function and the empty _editorInstances object in the non-fragment RichTextEditor.tsx... then import just the _editorInstances object here and add / remove this editor to it, and import getEditor in the top-level index.tsx to attach it to the main namespace.

The advantages of that are (1) users can depend on getEditor existing from the beginning, whether or not an editor has been rendered, and (2) _editorInstances doesn't need to be exposed in the main namespace at all (though the latter you could accomplish by making it a constant outside the component in this file).

Also id is a string by the time it gets to the component being rendered, but to support PMCs should getEditor call stringifyId on it?

@AnnMarieW
Copy link
Copy Markdown
Collaborator Author

Thanks @BSd3v for your help getting the updated version working 🤗

Copy link
Copy Markdown
Collaborator

@alexcjohnson alexcjohnson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great!

@AnnMarieW AnnMarieW merged commit 053b446 into snehilvj:master Nov 6, 2025
1 check passed
@AnnMarieW AnnMarieW deleted the rte-expose-editor branch November 6, 2025 15:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants