Izuagbala
Izuagbala

Reputation: 449

How to use dash callback without an Input

I am trying to call a plotly-dash callback without the Input and the method won't fire.

This is a dashboard I am trying to build using dash. In the past when I use a callback with both the Input and Output everything works fine but when I tried using only output the result is not displayed on the dashboard.

html.Div(
    [

        html.P(
            "Tweet Count",
            className="twelve columns indicator_text"
        ),
        html.P(
            id = 'tweet_value',
            className="indicator_value"
        ),
    ],
    className="four columns indicator",

)

@app.callback(
Output("tweet_value","children")

)
def total_tweet_callback():

    return 100   

Upvotes: 19

Views: 34149

Answers (3)

Kermit
Kermit

Reputation: 5972

You could can use an dcc.Interval.

It works when refreshing the page.

from datetime import datetime

# within layout
dcc.Interval(
    id="load_interval", 
    n_intervals=0, 
    max_intervals=0, #<-- only run once
    interval=1
),
html.Span(
    id="spanner",
    style=dict(color="yellow") #<-- just so it's easy to see
),

# callback
@app.callback(
    Output(component_id="spanner", component_property="children"),
    Input(component_id="load_interval", component_property="n_intervals"),
)
def update_spanner(n_intervals:int):
    return datetime.now()

I need to refresh the initial data periodically anyways so its good to get familiar with Interval. n_intervals is kind of like n_clicks.

https://dash.plotly.com/dash-core-components/interval


Disclaimer; my approach above is kind of a hack and I don't know if it will hold up long term.

Upvotes: 7

Shovalt
Shovalt

Reputation: 6766

There is a need for at least one input or event for a callback to get called, as written inside the dash.py code:

Without Input or Event elements, this callback will never get called.

(Subscribing to input components will cause the callback to be called whenever their values change and subscribing to an event will cause the callback to be called whenever the event is fired.)

In your case - if there is no trigger for the callback, why use a callback? If you want total_tweet_callback to run only once on load, simply call it from the layout:

def total_tweet_callback():
    return 100

app.layout = lambda: html.Div(
    [
        html.P(
            "Tweet Count",
            className="twelve columns indicator_text"
        ),
        html.P(
            children=total_tweet_callback(),
            id='tweet_value',
            className="indicator_value"
        ),
    ],
    className="four columns indicator",
)

Notice that:

  1. I removed the decorator from total_tweet_callback.
  2. I gave the layout a function (lambda function in this case) that returns the Div element. This isn't necessarily required, and depends on other aspects of your code. For example, including the lambda: will cause the total_tweet_callback function get called each time the page is reloaded, while removing it will get the value only once when the app is loaded.

Upvotes: 19

zr67800
zr67800

Reputation: 151

All callbacks are run once when loaded, except disabled explicitly. So a simple solution is to use a dummy input, referring to anything, and just not using it.

I do not agree with the other answer. Directly calling the function would not make it triggered every 'load'. In that way the function only run once when the statement is run. The function is only triggered when the app is started, not every time you click refreshing button of your browser. If you use datetime.datetime.now() there, you can see the difference.

Upvotes: 13

Related Questions