0

I am a newb, and currently working in dash through windows. I have the following script in which I am trying to update a graph with different values by clicking on a button. The program is really simple, but can't make it work so far. I have researched here and in the dash community but to no avail.

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

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

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

# Some color in here
colors = {
    'background': '#111111',
    'text': '#7FDBFF'
}

# this graph appears by default, but is never updated
trace_1 = go.Scatter(
            x = [5, 4, 3, 2, 1, 20, 2.5, 3],
            y = [1, 2, 3, 5, 7.3, -11, 7, 5]
        )

layout = go.Layout(title = 'Título de gráfica')
fig = go.Figure(data = [trace_1], layout = layout)

app.layout = html.Div(style = {'backgroundColor': colors['background']},
    children = [
    html.H3(
        children = 'Some title in here', 
            style = {
            'textAlign': 'center',
            'color': colors['text']
        }
    ),
    
# Button
    html.Button(
        children = 'Change', 
        id = 'button-1',
        n_clicks = 0,
        style = {
            'color': colors['text']
        }
    ),


html.Div(
    [
    html.Br(),
    html.Br(),
    html.Label(
        ['choose something'],
        style = {
            'font-weight': 'bold',
            'text-align': 'center',
            'color': colors['text']
        }
    ),
#These values are not working right now... just for fun right now
        dcc.Dropdown(
            id = 'dropo_1',
            options = [
                {'label' : '2048', 'value':'2048'},
                {'label' : '2560', 'value':'2560'},
                {'label' : '3200', 'value':'3200'}
            ],
            value = '2048',
            multi = False,
            disabled = False,
            persistence = 'string',
            persistence_type = 'session'
        ),
        html.Br(),
        dcc.Dropdown(
            id = 'dropo_2',
            options = [
                {'label' : '2048', 'value':'2048'},
                {'label' : '2560', 'value':'2560'},
                {'label' : '3200', 'value':'3200'}
            ],
            value = '2048',
            multi = False,
            disabled = False,
            persistence = 'string',
            persistence_type = 'session'
        )
        ],className = 'three columns'
    ),

    
# graph
    html.Div(
        [
        dcc.Graph(id = 'graf-1', figure = fig)
        ],className = 'eight columns'
    )
    ]
)

# Click and other values
@app.callback(
    Output('graf-1', 'fig'),
    [Input('button-1', 'n_clicks')]
)

def update_values(n_clicks):
    changed_id = [p['prop_id'] for p in dash.callback_context.triggered][0]

    if 'button-1' in changed_id:

        trace_1 = go.Scatter(
            x = [5, 2, 5, 1, 7, 2, 3, 7],
            y = [3, 4, 3, 4, 3, 5, 7, 8]
        )
        layout = go.Layout(title = 'Nueva gráfica')
        fig = go.Figure(data = [trace_1], layout = layout)
        return (fig) 
    else:
        print('not working')
        

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

The program allows me to upload it to my local host, but the button is not working, the graph won't update, and dash is telling me about that error (pay no attention to the different titles): enter image description here

Eduardo
  • 45
  • 9

2 Answers2

0

To update a ddc.Graph component, you need to update the figure rather than 'fig'.

@app.callback(
    Output('graf-1', 'figure'),
    [Input('button-1', 'n_clicks')]
)
Chuck Tucker
  • 259
  • 1
  • 8
  • Thanks for the quick reply, Chuck Tucker. I changed figure instead of fig, as you were telling me.The error is gone, but when I click on the button nothing is happening. The graph doesn't show at all, and after a while my web browser is telling me that the page is unresponsive. – Eduardo Jun 14 '21 at 20:13
  • Unless you're using a version of plotly I'm not familiar with it should be `import plotly.graph_objects as go` rather than 'graph_objs'. Not sure if it would produce the error you're seeing, but you also have some indentation issues in your html.Div that includes the dropdowns. – Chuck Tucker Jun 15 '21 at 21:13
0

Chuck Tucker, In some scripts I have plotly.graph_objs, and in some others I have plotly.graph_objects, but that doesn't seem to be the problem. I was reading from various sources, especially from here

And there is the PreventUpdate that seems to be very important. I am also ignoring the html.button for the daq.BooleanSwitch (html.Button takes a value of None, and seems that it was adding to my problems)... Anyways... after so many tries and re-does I am posting the solution (in case more newbs are stuck with this kind of problems):

import dash
import dash_daq as daq
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import plotly.graph_objects as go
from dash.exceptions import PreventUpdate

# Esto llama un archivo .css para hacer la partición html.
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']

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

# Le damos color a esto
colors = {
    'background': '#111111',
    'text': '#7FDBFF'
}
trace_1 = go.Scatter(
    x = [2,3,4,5,6,7,8,9,10,11,12,13,14,15],
    y = [4,6,8,10,12,14,16,18,20,22,24,26,28,30]
)

layout = go.Layout(title = 'Título de gráfica')
fig = go.Figure(data = [trace_1], layout = layout)


app.layout = html.Div(style = {'backgroundColor': colors['background']},
    children = [

# H3 es para marcar el título, es el mediano que los demás, H1 es súper grande.
    html.H3(
        children = 'Ejemplo fácil para chequear botones-gráficas-menus', 
            style = {
            'textAlign': 'center',
            'color': colors['text']
        }
    ),

# Div parece que divide éste párrafo abajo de lo anterior
    html.Div(
        id= 'respuesta',
        children= 'Clickea el botón',
          style = {
            'textAlign': 'center',
            'color': colors['text']
        }
    ),
# Se define el botón:
    daq.BooleanSwitch(
        id = 'Swtc_1',
        on = False
    ),
    
    html.Div(
        [
        html.Br(),
        html.Br(),
        html.Label(
            ['Elija algo'],
            style = {
                'font-weight': 'bold',
                'text-align': 'center',
                'color': colors['text']
            }
        ),
        dcc.Dropdown(
            id = 'dropo_1',
            options = [
                {'label' : '2048', 'value':'2048'},
                {'label' : '2560', 'value':'2560'},
                {'label' : '3200', 'value':'3200'}
            ],
            value = '2048',
            multi = False,
            disabled = False,
            persistence = 'string',
            persistence_type = 'session'
        ),
        html.Br(),
        dcc.Dropdown(
            id = 'dropo_2',
            options = [
                {'label' : '2048', 'value':'2048'},
                {'label' : '2560', 'value':'2560'},
                {'label' : '3200', 'value':'3200'}
            ],
            value = '2048',
            multi = False,
            disabled = False,
            persistence = 'string',
            persistence_type = 'session'
        )
        ],className = 'three columns'
    ),
        
# Ponemos la gráfica
    html.Div(
        [
        dcc.Graph(id = 'plot_id', figure = fig)
        ],className = 'eight columns'
    )
    ]
)

# Acá se genera la interacción.
@app.callback(
    Output('plot_id', 'figure'),
    [Input('Swtc_1', 'on')]
)

# Función 
def update_output(on):
    if on is True:
        trace_1 = go.Scatter(
            x = [4,6,8,10,12,14,16,18,20,22,24,26,28,30],
            y = [2,3,4,5,6,7,8,9,10,11,12,13,14,15]
        )
        layout = go.Layout(title = 'Título de gráfica')
        fig = go.Figure(data = [trace_1], layout = layout)
        return (fig)
    else:
        raise PreventUpdate
        
   

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

So, right now is working, and it's updating the graph with the new values.

P.s.- And for the newbs like me, remember to install dash_daq as well (pip install dash_daq) (I got stuck and it's not pre-installed with dash)

Eduardo
  • 45
  • 9