Can I access a component's data without triggering on it?

Hi all,

I’m getting started with Plotly Dash, and trying to use the trick of storing JSON-encoded data in a hidden div.

I have a couple of chained callbacks which update UI elements when the data changes. I need a callback further down the chain to be able to read the JSON-encoded data - but I don’t want the div to be an Input to that callback, as I don’t want the callback to trigger when it changes. The triggering should occur earlier in the chain.

I thought that I could achieve this by examining app.layout['hidden_div'].children from within my callback. I realise I’m not supposed to directly modify the state of this variable as it’s outside the scope of my function, but I thought reading it would be ok. However it appears that even reading the variable is causing problems (if I am actually supposed to be able to read the variable, I’ll go into detail on the issues I seem to be getting).

Is reading a component directly, such as app.layout['hidden_div'].children, supposed to be allowable from within a callback? If not, is there a correct way for a callback to read data from a component without triggering on it?

Thanks for any help!

1 Like

Instead of Input, use State.

State provides value, but does not trigger callback.

app.callback(self, output, inputs=[], state=[], events=[]) has two positional arguments (output, inputs), and two keyword arguments (state, events).


Lets say you have 2 inputs, but you want the second one to just pass value, then instead of:

@app.callback(Output('output-name', 'property'),
    [Input('input1-name', 'property'), Input('input2-name', 'property')])
def callback_function(input1, input2):
    pass

you can do:

@app.callback(Output('output-name', 'property'),
    [Input('input1-name', 'property')],
    state=[State('input2-name', 'property')])
def callback_function(input1, input2):
    pass

This way only input1-name will fire the callback, but both inputs will pass value to it.


You can also use events keyword to pass inputs that will fire the callback, without passing the value:

@app.callback(Output('output-name', 'property'),
    [Input('input1-name', 'property')],
    events=[Event('input2-name', 'property')])
def callback_function(input1):
    pass

This way both inputs will fire the event, but only input1-name will pass the value.


Combining it together, you can achieve something like:

@app.callback(Output('output-name', 'property'),
    state=[State('input1-name', 'property')],
    events=[Event('input2-name', 'property')])
def callback_function(input1):
    pass

Now only input2-name will fire the callback, but input1-name will pass the value.

2 Likes

Great, thank you! Exactly what I needed to know!