dash icon indicating copy to clipboard operation
dash copied to clipboard

Allow for "null" / no output callbacks

Open tr8dr opened this issue 4 years ago • 8 comments

Dash callbacks currently require at least one output. There are scenarios where one would like to act on an event from the UI, producing no output as a side-effect. Would like to be able to do:

@app.callback(None, [Input("A","value"), Input("B", "value")]
def handler(a, b):
    <some application logic>
    return

Right now one has to create a dummy container (such as a div) in the DOM and use it as a "fake" output sink:

    ...
    html.Div(id='dummy1'),
    ...

@app.callback(Output("dummy1", "children"), [Input("A","value"), Input("B", "value")]
def handler(a, b):
    <some application logic>
    return None

tr8dr avatar Feb 08 '21 18:02 tr8dr

This is all the more relevant with clientside callbacks; an example is using them as some sort of post-update hook to create clientside-only behaviour:

app.clientside_callback(
    """
    function(fig) {
        document.querySelector("#graph .js-plotly-plot").on("plotly_hover", event => {
            ...
        })
        return null // we can't even use dash.no_update in here
    }
    """,
    Output('dummy', 'children'), # ideally we should not need this
    Input('graph', 'figure')
)

jeslinmx avatar May 07 '22 08:05 jeslinmx

Hi guys, I'm new here. I'd like to tackle this if possible. I've had that need myself before.

kenshima4 avatar Jul 18 '23 20:07 kenshima4

@kenshima4 you're more than welcome to give it a shot. It would be a great feature but it's not one Plotly staff currently have in our roadmap. Just be aware that it may have a number of complications - the ones that occur to me offhand are validation, determining when to trigger, MATCH pattern-matching inputs, and inclusion in the devtools callback graph - and will require quite a few tests as a result to give us confidence in the implementation. One piece of good news is that since we added allow_duplicate=True we have the machinery to support multiple no-output callbacks, as long as we implicitly set this flag in this case.

alexcjohnson avatar Jul 19 '23 18:07 alexcjohnson

Hi @alexcjohnson I just wanted to say that I can still try and solve it but maybe at a later stage (if somebody else wants to give it a shot that's ok). My apologies but I have a few other projects that just came my way. Don't have too much time now.

kenshima4 avatar Jul 27 '23 09:07 kenshima4

It's finally possible! You can now create callbacks without providing any outputs!! Just clone this fork] and run your code without any issues. You'll have to explicitly set a flag force_no_output=True (similar to what @alexcjohnson referred). While the flag is a temporary fix, I'm trying a general approach to make this work. Till then, give this a try. Usage:

from dash import Dash, html, callback, Output, Input

app = Dash(__name__)

app.layout = html.Div([
    html.H1(children='Title of Dash App', style={'textAlign':'center'}),
    html.Div(id="result"),
    html.Button(id='output-button',children="This button gives an output"),
    html.Button(id='no-output-button',children="no output button"),

])

@callback(
    Output("result","children"),
    Input("output-button","n_clicks")
)
def make_result(n_clicks):
    return f"Button with output looks like this {n_clicks}"

@callback(
    Input("no-output-button","n_clicks"),
    force_no_output=True
)
def make_result(n_clicks):
    print("Ignored",n_clicks)
    return None


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

yashjha123 avatar Aug 07 '23 11:08 yashjha123

Thank you @yashjha123 this look great, I think instead of having the force_no_output argument you can check that with length of the outputs and set the flag for the renderer. We will be happy to look at a PR if you want.

T4rk1n avatar Aug 07 '23 18:08 T4rk1n

@yashjha123 do you plan on opening a pull request for this? I think it would be nice to have in the upstream.

alexk101 avatar Oct 05 '23 16:10 alexk101

Sorry to kept you all waiting. I just opened a PR. Can you take a review? @alexk101

yashjha123 avatar Oct 31 '23 21:10 yashjha123