Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Allow for "null" / no output callbacks #1549

Closed
tr8dr opened this issue Feb 8, 2021 · 8 comments · Fixed by #2822
Closed

Allow for "null" / no output callbacks #1549

tr8dr opened this issue Feb 8, 2021 · 8 comments · Fixed by #2822
Assignees

Comments

@tr8dr
Copy link

tr8dr commented Feb 8, 2021

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 tr8dr changed the title Allow for no output callbacks Allow for "null" / no output callbacks Feb 8, 2021
@jeslinmx
Copy link

jeslinmx commented May 7, 2022

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')
)

@kenshima4
Copy link

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

@alexcjohnson
Copy link
Collaborator

@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.

@kenshima4
Copy link

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.

@yashjha123
Copy link

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)

@T4rk1n
Copy link
Contributor

T4rk1n commented Aug 7, 2023

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.

@alexk101
Copy link

alexk101 commented Oct 5, 2023

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

@yashjha123
Copy link

yashjha123 commented Oct 31, 2023

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

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

8 participants