Black Lives Matter. Please consider donating to Campaign Zero's mission of ending police violence in America.
https://www.joincampaignzero.org

Dependency Issue

I have some code that illustrates an issue. I have two input fields.
If I input x, I want to calculate x2 as 2 * x.
If I input x2, I want to calculate x as x2 / 2.0
For the actual problem, the calculation is more complex.

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

external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']


def generate_float_input(name: str, label: str, value: float) -> html.Div:
    label = html.Label(label)
    inpt = dcc.Input(id=name, type='number',
                     value=value,
                     style={'border-style': 'solid',
                            'border-color': 'black',
                            'width': '100%',
                            'background-color': 'LightGreen',
                            'color': 'Black',
                            'border-width': 'thin'})
    return html.Div([label, inpt], style={'columnCount': 2})


app = dash.Dash(__name__, external_stylesheets=external_stylesheets)

app.layout = html.Div(
    [
        html.Div(
            children=
            [
                generate_float_input("x", "X", 10),
                generate_float_input("x2", 'x2', 100)
            ],
        )
    ]
)


@app.callback(
    Output(component_id="x2", component_property='value'),
    [
        Input(component_id="x", component_property='value')
    ],
)
def x(value):
    print(value)
    return value * 2.0

# Fails - Error loading dependencies

@app.callback(
    Output(component_id="x", component_property='value'),
    [
        Input(component_id="x2", component_property='value')
    ],
)
def x2(value):
    print(value)
    return value / 2.0

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

The issue is on the second callback that generates an “Error loading dependencies” message. I understand why, its a question on a work around

Now I suspect the dependency issue is to prevent a cascade of updates that never stops.

Can I do something like this? In the call back for both items, do a check to see if the value is unchanged, and return dash.no_update preventing the cascade that never stops?

Or can I directly set the value of the input, render it, at a lower level such that it doesn’t have to appear as an output in the call back?

Any help welcome.

N.

Best to use dash.callback_context so you can avoid the circular dependency:

@app.callback(
    [
        Output(component_id="x", component_property='value'),
        Output(component_id="x2", component_property='value')
    ],
    [
        Input(component_id='GO_Button', component_property='n_clicks'),
    [
        State(component_id="x", component_property='value'),
        State(component_id="x2", component_property='value'),
    ]
)
def computation(clicks, x, x2):
    ctx = dash.callback_context
    # Handle initial loading of app
    if not ctx.triggered:
        return dash.no_update, dash.no_update

    return x * 2, x / 2.0

Traceback (most recent call last):
  File "N:/PycharmProjects/test/test.py", line 44, in <module>
    Input(component_id="x2", component_property='value'),
  File "C:\Users\nleaton\.conda\envs\qbase\lib\site-packages\dash\dash.py", line 1231, in callback
    self._validate_callback(output, inputs, state)
  File "C:\Users\nleaton\.conda\envs\qbase\lib\site-packages\dash\dash.py", line 975, in _validate_callback
    "Same output and input: {}".format(bad)
dash.exceptions.SameInputOutputException: Same output and input: x.value

it checks for that, and prevents it.:frowning:

OMG…I cant believe I posted that code…too early coding w/o coffee…

Before I continue helping, can you update your code to include the definitions of the x and x2 component id’s? Why are you wanting to “abort” the circular reference?

I updated my example to introduce a GO button…pressing this button triggers the callback to update x and x2 based on their current state…eliminating the circular referece. This may work for you depending on your use case…or could help spawn another solution.