📣 Dash v1.7.0 released - Async component fixes, inline clientside callbacks, and bug fixes

Update: version 1.16 has been released since this was posted.

Dash 1.7.0 is a minor release adding support for inline clientside callbacks, improving dcc’s Slider and RangeSlider styling and behavior, and fixing some additional bugs for async components.

Changelog
Dash v.1.7.0

Highlights

Previous Releases

In Depth

Inline Clientside Callbacks

import dash
import dash_html_components as html
import dash_core_components as dcc
from dash.dependencies import ClientsideFunction, Input, Output

app = dash.Dash(__name__)

app.layout = html.Div([
    dcc.Input(id='input'),
    html.Div(id='output-clientside'),
    html.Div(id='output-serverside')
])

@app.callback(
    Output('output-serverside', 'children'),
    [Input('input', 'value')])
def update_output(value):
    return 'Server says "{}"'.format(value)


app.clientside_callback(
#     ClientsideFunction(
#         namespace='clientside',
#         function_name='display'
#     ),
    """
    function (value) {
        if (value && value.indexOf('--') === 0) {
            throw window.dash_clientside.PreventUpdate;
        }

        if (value && value.indexOf('__') === 0) {
            return window.dash_clientside.no_update;
        }

        return 'Client says "' + value + '"';
    }
    """,
    Output('output-clientside', 'children'),
    [Input('input', 'value')]
)

if __name__ == "__main__":
    app.run_server(port=8070)
8 Likes

The upgrade of dash from 1.6.1 to 1.7.0 seems to have broken one of my applications. Specifically, i have observed that some of the callback are now executed multiple times, with the final state of the page not correspond to the latest state.

Has there been any changes to how the (normal server side) callbacks are handled?

after update, my initial client side callbacks does not work. it resides in assets/ folder.
is there anything missing to re-make it work?

@dingx @Emil I’m not aware of anything that has changed that would break existing apps, but it’s always possible we’ve introduced a bug, or that you’re using - can you post a simplified version of your app so we can try to reproduce it on our side?

I have downgraded dash to 1.6.1 as a temporary fix.

in my case, I’m using something like:

let cells = document.getElementById()
cell.forEach()

and cells is of type htmlCollection, and after update it throws error because it‘s not array and has no forEach method.
i fixed it like following:

Array.from(cells).forEach()

I downgraded to 1.6.1 as well. None of my charts were updating on the initial page load. If I waited longer than the callback interval, the charts would update though. I came across the following open bug, which may be related: https://github.com/plotly/dash/issues/1071

Plotly Team - If there’s anything I can provide to assist in researching this, just let me know.

I think that i have (finally) succeeded in creating an MWE for demonstrating the bug,

Can you reproduce it, @alexcjohnson?

Thanks @Emil - I’m just finishing up (I think… I hope!) a complete overhaul of our callback handling system, as part of creating a wildcards framework https://github.com/plotly/dash/issues/475 - I’ll take a look at your example, along with the other callback bugs that have popped up, once I get the existing tests all working :slight_smile: Stay tuned!

That sounds great! I am looking forward to trying out the new implementation :grinning:

@alexcjohnson - I tested version 1.9.0 and the callback issue is still present. It seems like a race condition. I have several callbacks that use a dropdown as an input. However, the values and options for that dropdown are updated by another callback when the page or tab is loaded. I suspect the other callbacks are failing simply because the dropdown input isn’t ready yet. Is there a proper way to handle this scenario or is this a bug?

@alexcjohnson - I’ve been cleaning up my callbacks and I no longer have an issue with components not loading.

1 Like

Can I have an example because I don’t really get what the ClientsideFunction(namespace='clientside', function_name='display') is referring to?
Is it something static that has to be there for the interpreter to understand? Nothing to change here?

What I understand is that there will be kind of onChange JS event listener on the element with id=input that will trigger the JS function in multiline quotes to run clientside only to update the element with id= output-clientside. Am I right?

Last question what happens if I have a core.Store element as a State entry for this clientside function? Store elements are stored in the browser right? So everything should happens clientside

It would be really awesome :pray:

Thanks

The commented out ClientsideFunction is a reference to the other way of defining a clientside callback without using inlined JS functions and is not required. I agree that it’s not really clear. Sorry about that.

With ClientsideFunction, you would need to define a function in a JS file in your assets folder with the desired callback code. For example, in this case:

if (!window.dash_clientside) {
    window.dash_clientside = {};
}
window.dash_clientside.clientside = {
    display: function (value) {
        if (value && value.indexOf('--') === 0) {
            throw window.dash_clientside.PreventUpdate;
        }

        if (value && value.indexOf('__') === 0) {
            return window.dash_clientside.no_update;
        }

        return 'Client says "' + value + '"';
    }
}

The value of that store’s prop at the time of the callback will be passed to the JS function to be used just like the input prop. Everything should happen clientside.