# How to detect changes by javascript in dash

**URL:** <https://community.plotly.com/t/how-to-detect-changes-by-javascript-in-dash/83397>\
**Category:** Dash Python\
**Created:** [March 27, 2024, 9:07pm UTC](https://community.plotly.com/t/how-to-detect-changes-by-javascript-in-dash/83397 "2024-03-27T21:07:08Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![kuplo](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/kuplo/32/27510_2.png) [@kuplo](https://community.plotly.com/u/kuplo)\
**Post date:** [March 27, 2024, 9:07pm UTC](https://community.plotly.com/t/how-to-detect-changes-by-javascript-in-dash/83397/1 "2024-03-27T21:07:08Z")

</div>

I want to use javascript for speed updates of a lot of elements (id to some value)

Here is the prototype, where I test different ways of changing elements with js. But callback can detect only one of them, fired by Output.

![Screen Recording 2024-03-27 at 22.15.07](https://us1.discourse-cdn.com/flex024/uploads/plot/original/3X/6/1/618cd92e235d8cb56d398064ae8376e320789e72.gif)

```auto
from dash import html, Output, Input, Dash, no_update
import json
import time

app = Dash( __name__ )
app.layout = html.Div(
    [
        html.Button("testing1", "testing1"),
        html.Div(id="test1"),
        html.Div(id="test1_javascript"),
        html.Div(id="test1_javascript_as_component"),
        html.Div(id="test1_javascript_as_reactdom"),
        html.Div(id="log"),
    ]
)

app.clientside_callback(
    """function (n) {
        function render_react_element(element){
            const { type, namespace, props } = element;
            // Validate data (optional, add checks for type and namespace)
            // Construct the element based on type and namespace
            const Element = window[namespace][type];
            console.log(`Element for ${element}:`, typeof(Element), Element);
            const created_element = React.createElement(Element, props);
            return created_element;
        }

        document.getElementById('test1_javascript').innerText=`update with js, n=${n}`;

        let dom_value = window.dash_html_components.H1({"children": `value from reactdom ${n}`});
        console.log('dom_value: ' , typeof(dom_value), dom_value);
        ReactDOM.render(dom_value, document.getElementById('test1_javascript_as_reactdom'));

        if (n) {
                    const element = 
                        """
    + json.dumps(html.H1(f"test1").to_plotly_json())
    + """
                console.log('element: ' , typeof(element), element);
                // document.getElementById('test1_javascript_as_component').innerText=element;

                if (1){
                    const created_element = render_react_element(element);

                    console.log('created_element: ', typeof(created_element), created_element);
                    ReactDOM.render(created_element, document.getElementById('test1_javascript_as_component'));
                }

                return element;
        }
        return window.dash_clientside.no_update
    }""",
    Output("test1", "children"),
    Input("testing1", "n_clicks"),
)

@app.callback(
    Output("log", "children"),
    [
        Input("test1", "children"),
        Input("test1_javascript", "children"),
        Input("test1_javascript_as_reactdom", "children"),
        Input("test1_javascript_as_component", "children"),
    ],
)
def detect_changes_with_javascript(*changes):
    print(f"{changes=}")
    if changes:
        time.sleep(0.5)
        return [html.Div(f"detected {changes=}")]
    return no_update

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

```

Why is it so?  
How to change the state of such elements, to make those changes visible in the dash?

---

<div class="post-metadata">

**Author:** ![jinnyzor](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/jinnyzor/32/21194_2.png) [@jinnyzor](https://community.plotly.com/u/jinnyzor)\
**Post date:** [March 27, 2024, 9:29pm UTC](https://community.plotly.com/t/how-to-detect-changes-by-javascript-in-dash/83397/2 "2024-03-27T21:29:56Z")

</div>

Hello @kuplo,

This is due to the nature of JS vs React, when altering only in JS, you dont have anything adjusting the state in React, thus the props never go back to dash.

However, in version `2.16.1`+ in dash, you now have access to `set_props` of `dash_clientside` which allows for you to trigger updates and callbacks straight from JS.

```auto
dash_clientside.set_props(id, propsToUpdate)

```

This will then trigger updates in the dash ecosystem like you are expecting.

---

<div class="post-metadata">

**Author:** ![AnnMarieW](https://avatars.discourse-cdn.com/v4/letter/a/ec9cab/32.png) [@AnnMarieW](https://community.plotly.com/u/AnnMarieW)\
**Post date:** [March 27, 2024, 10:36pm UTC](https://community.plotly.com/t/how-to-detect-changes-by-javascript-in-dash/83397/3 "2024-03-27T22:36:38Z")

</div>

You can find an example of what @jinnyzor recommended here:

> [@Changing the value of a input from javascript callback does not trigger the callback associated with that input](https://community.plotly.com/t/changing-the-value-of-a-input-from-javascript-callback-does-not-trigger-the-callback-associated-with-that-input/82922/2):
>
> Hi @mainul Good timing! This is possible as of dash 2.16.1 by using dash\_clientside\_set\_props The docs aren’t available yet, but you use it like this: dash\_clientside.set\_props(id, {props to set}) so in your case it would be: dash\_clientside.set\_props("last-key-pressed", {value: event.key}) Here’s the whole callback app.clientside\_callback( """ function(n\_clicks) { document.addEventListener('keydown', function(event) { const allowedKeys = ['ArrowL…

---

<div class="post-metadata">

**Author:** ![kuplo](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/kuplo/32/27510_2.png) [@kuplo](https://community.plotly.com/u/kuplo)\
**Post date:** [March 28, 2024, 4:14pm UTC](https://community.plotly.com/t/how-to-detect-changes-by-javascript-in-dash/83397/4 "2024-03-28T16:14:30Z")

</div>

Thanks!  
Changed my code, added also changes Store from js. All is detectable now.

For someone who will search for the solution:

```auto
from dash import html, Output, Input, Dash, no_update, dcc
import json
import time

app = Dash( __name__ )
app.layout = html.Div(
    [
        html.Button("testing1", "testing1"),
        html.Div(id="test1"),
        html.Div(id="test1_javascript"),
        html.Div(id="test1_javascript_as_component"),
        html.Div(id="test1_javascript_as_reactdom"),
        dcc.Store(id="js_data_store", data={}),
        html.Div(id="log"),
    ]
)

app.clientside_callback(
    """function (n) {
        function render_react_element(element){
            const { type, namespace, props } = element;
            // Validate data (optional, add checks for type and namespace)
            // Construct the element based on type and namespace
            const Element = window[namespace][type];
            console.log(`Element for ${element}:`, typeof(Element), Element);
            const created_element = React.createElement(Element, props);
            return created_element;
        }

        // document.getElementById('test1_javascript').innerText=`update with js, n=${n}`;
        dash_clientside.set_props("test1_javascript", {children: `update with js, n=${n}`});

        let dom_value = window.dash_html_components.H1({"children": `value from reactdom ${n}`});
        console.log('dom_value: ' , typeof(dom_value), dom_value);
        // ReactDOM.render(dom_value, document.getElementById('test1_javascript_as_reactdom'));
        dash_clientside.set_props('test1_javascript_as_reactdom', {'children':{'props': {'children': `value from reactdom ${n}`}, 'type': 'H1', 'namespace': 'dash_html_components'}})

        if (n) {
                    console.log('n:', n);
        
                    dash_clientside.set_props("js_data_store", {data: {'value':'new_value'}}); // working
                    
                    
                    const element = 
                        """
    + json.dumps(html.H1(f"test1").to_plotly_json())
    + """
                console.log('element: ' , typeof(element), element);
                // document.getElementById('test1_javascript_as_component').innerText=element;

                if (1){
                    const created_element = render_react_element(element);
                    console.log('created_element: ', typeof(created_element), created_element);
                    // ReactDOM.render(created_element, document.getElementById('test1_javascript_as_component'));
                    var children = JSON.parse(JSON.stringify(created_element))['props'];
                    console.log('test1_javascript_as_component', typeof(children), children);
                    // dash_clientside.set_props("test1_javascript_as_component", {children: element})
                    dash_clientside.set_props("test1_javascript_as_component", {children: [element, element]})
                }

                return element;
        }
        
        return window.dash_clientside.no_update
    }""",
    Output("test1", "children"),
    Input("testing1", "n_clicks"),
)

@app.callback(
    Output("log", "children"),
    [
        Input("test1", "children"),
        Input("test1_javascript", "children"),
        # Input("test1_javascript", "value"),
        Input("test1_javascript_as_reactdom", "children"),
        Input("test1_javascript_as_component", "children"),
        Input("js_data_store", "data"),
    ],
)
def detect_changes_with_javascript(*changes):
    print(f"{changes=}")
    if changes:
        return [html.Div(f"detected at {time.time()} {changes=}")]
    return no_update

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

```

For those who want to understand the speed of set\_props: [Dash\_clientside.set\_props 50 times slower than document.getElementById(id).innerText](https://community.plotly.com/t/dash-clientside-set-props-50-times-slower-than-document-getelementbyid-id-innertext/83425)
