# Update\_layout versus callback for checklists and dropdowns

**URL:** <https://community.plotly.com/t/update-layout-versus-callback-for-checklists-and-dropdowns/73827>\
**Category:** Dash Python\
**Created:** [March 23, 2023, 3:05pm UTC](https://community.plotly.com/t/update-layout-versus-callback-for-checklists-and-dropdowns/73827 "2023-03-23T15:05:35Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![tg550](https://avatars.discourse-cdn.com/v4/letter/t/e9bcb4/32.png) [@tg550](https://community.plotly.com/u/tg550)\
**Post date:** [March 23, 2023, 3:05pm UTC](https://community.plotly.com/t/update-layout-versus-callback-for-checklists-and-dropdowns/73827/1 "2023-03-23T15:05:36Z")

</div>

I have a line plot with a range slider and a dropdown to dynamically update the plot and this works very nicely, however, I would also like to remake this with a checklist instead of a dropdown, sounds simple but I’m struggling to display the data so it looks the same as the dropdown, which I love.

So far this is what I’ve done for my range slider dropdown and it works to my satisfaction.

```auto
import everything I need

path = r'C:\Users\2022.csv'
df = pd.read_csv(path)
df_zones = pd.DataFrame({
    'DK1': df['DK1'],
    'DK2': df['DK2'],
    'FI': df['FI'],
    'NO1': df['NO1'],
    'NO2': df['NO2'],
    'NO3': df['NO3'],
    'NO4': df['NO4'],
    'NO5': df['NO5'],
    'SE1': df['SE1'],
    'SE2': df['SE2'],
    'SE3': df['SE3'],
    'SE4': df['SE4'],
    })

fig = go.Figure(layout=go.Layout(
        title=go.layout.Title(text="Error (Results - Forecast)")
    ))

for column in df.columns.to_list():
    fig.add_trace(
        go.Scatter(
            x = df.index,
            y = df[column],
            name = column
        )
    )
    
fig.update_layout(
    updatemenus=[go.layout.Updatemenu(
        active=0,
        buttons=list(
            [dict(label = 'All zones',
                  method = 'update',
                  args = [{'visible': [True, True, True, True,True, True,True, True,True, True,True, True]},
                          {'title': 'All',
                           'showlegend':True}]),
             dict(label = 'DK',
                  method = 'update',
                  args = [{'visible': [True, True, False, False, False, False, False, False, False, False, False, False]}, # the index of True aligns with the indices of plot traces
                          {'title': 'Denmark',
                           'showlegend':True}]

# Here I've omitted all the other buttons I use for economy. 

)
    ])
fig.update_xaxes(rangeslider_visible=True) #ranges slider
fig.show()

```

Next is what I’ve attempted with the checklist and it displays, terribly. The graph is squeezed into the top 50% of the page and the buttons don’t work yet. Each selection of a checklist button should update the graph and display the new data. I think I’ve misunderstood something in the two approaches but these two methods produce vastly different results and I don’t understand why.

I’m aware I need to add some functionality to update the graph with the ‘y’ component but before I do that I want to be clear on what is the best method and why.

When should I use a callback for a graph update? and is it better than the update\_layout method? What is the difference here and what would make the most sense for me to do to replicate my first attempt?

```auto

DK = df.columns[1:3]
FI = df.columns[3:4]
NO = df.columns[4:9]
SE = df.columns[9:13]

#%%

zone_dict = {'DK':'Denmark', 'FI':'Finland', 'NO':'Norway', 'SE':'Sweden' }
ID = 'DK'
zone_ID = zone_dict[ID]

# Create the line graph
line_graph = px.line(
  # Set the appropriate DataFrame and title
  data_frame= df, title='Flow for '+zone_ID, 
  # Set the x and y arguments
  x='DateTimeUtc', y= ['DK1','FI'])
  
# Create the Dash app
app = dash.Dash( __name__ )

# Set up the layout with a single graph, inside a children argument so we can add multiple elements
# ID's also important for callbacks
app.layout = html.Div(children = [html.H1('Error'), 
                                  dcc.Checklist(id='my-checklist', options=[{'label': col, 'value': col} for col in df.columns],
        value=df.columns.tolist(),
        labelStyle={'display': 'inline-block'}
    ),
    dcc.Graph(id='my-line-graph', figure=line_graph)
])
line_graph.update_xaxes(rangeslider_visible=True)

# Set the app to run in development mode
if __name__ == ' __main__':
    app.run_server(debug=False)

```

Head of dataframe

```auto

NDFrame.head of DK1 DK2 ... SE3 SE4
DateTimeUtc ...                      
2022-01-01 00:00:00 1691.712 463.951 ... -112.99925 93.56625
2022-01-01 01:00:00 1244.341 318.301 ... 68.27500 345.15800
2022-01-01 02:00:00 927.078 175.081 ... 308.46300 648.40400
2022-01-01 03:00:00 612.140 43.902 ... 450.57400 935.90600
2022-01-01 04:00:00 934.235 98.501 ... 559.55400 794.34800
                      ... ... ... ... ...
2022-12-31 20:00:00 2217.632 -54.234 ... 581.45780 577.19120
2022-12-31 21:00:00 2751.985 -105.601 ... 605.69085 521.62715
2022-12-31 22:00:00 2972.932 -100.368 ... 725.38635 485.12365

```

Thanks for any input.

---

<div class="post-metadata">

**Author:** ![hoatran](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/hoatran/32/21447_2.png) [@hoatran](https://community.plotly.com/u/hoatran)\
**Post date:** [March 24, 2023, 1:21am UTC](https://community.plotly.com/t/update-layout-versus-callback-for-checklists-and-dropdowns/73827/2 "2023-03-24T01:21:10Z")

</div>

Don’t have your dataframe so I think you can refer something to revise your code:

- You need to use `callback` to return new data to your figure.
- In`dcc.Graph` instead of define `figure=line_graph` I think you should use `figure={}` and then return new Graph with callback.

```auto
from dash import Dash, dcc, html, dcc, Input, Output
from dash.exceptions import PreventUpdate
import pandas as pd
import dash_bootstrap_components as dbc
import pandas as pd
import plotly.express as px

df = px.data.gapminder().query("country==['Canada']")
app = Dash( __name__ , external_stylesheets=[dbc.themes.LUX])
app.layout = html.Div([
    dbc.Row([
        dbc.Col([
            dbc.Checklist(id='my-checklist', options=[{'label':x, 'value':x} for x in df.columns[3:6]],
                          value=df.columns[3],inline=True),
                         dcc.Graph(id='my-line-graph', figure={})
        ])
    ])
])

@app.callback(Output('my-line-graph', 'figure'),
             Input('my-checklist','value'))
def update_line_graph(my_checklist):
    if my_checklist != []:
        fig = px.line(df, x="year", y=my_checklist, title='Life expectancy in Canada')
        return fig
    else:
        raise PreventUpdate
if __name__ == " __main__":
    app.run_server(debug=False)

```

 ![Screenshot 2023-03-24 090610](https://us1.discourse-cdn.com/flex024/uploads/plot/original/3X/5/e/5ea5aacf7255ca36594eb306fbfe6620bc3ba067.png)

---

<div class="post-metadata">

**Author:** ![tg550](https://avatars.discourse-cdn.com/v4/letter/t/e9bcb4/32.png) [@tg550](https://community.plotly.com/u/tg550)\
**Post date:** [March 24, 2023, 7:22am UTC](https://community.plotly.com/t/update-layout-versus-callback-for-checklists-and-dropdowns/73827/3 "2023-03-24T07:22:29Z")

</div>

Aha! Thanks for the tip. I’ve added my df.head for consistency.

One question though, I was always taught to make a copy of the df before updating but you don’t do this. Is it not necessary?

---

<div class="post-metadata">

**Author:** ![hoatran](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/hoatran/32/21447_2.png) [@hoatran](https://community.plotly.com/u/hoatran)\
**Post date:** [March 24, 2023, 7:25am UTC](https://community.plotly.com/t/update-layout-versus-callback-for-checklists-and-dropdowns/73827/4 "2023-03-24T07:25:39Z")

</div>

Can you upload data to somewhere that I can download and run?

---

<div class="post-metadata">

**Author:** ![tg550](https://avatars.discourse-cdn.com/v4/letter/t/e9bcb4/32.png) [@tg550](https://community.plotly.com/u/tg550)\
**Post date:** [March 24, 2023, 8:01am UTC](https://community.plotly.com/t/update-layout-versus-callback-for-checklists-and-dropdowns/73827/5 "2023-03-24T08:01:10Z")

</div>

Thanks, I got it to work now but I have a couple more questions. I can’t send you the df but I can build one for you that’s the same:

```auto

df_2 = pd.DataFrame(np.random.randint(0,100,size=(8761, 12)), columns=list('ABCDEFGHIJKL'))
df = pd.date_range(start='1/1/2018', end='1/1/2019', freq= 'H')
df_2.set_index(df)

```

- Why does the graph squeeze up to the top 33% of the page when displaying using this method? When I use the first method it fills the full page.

---

<div class="post-metadata">

**Author:** ![hoatran](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/hoatran/32/21447_2.png) [@hoatran](https://community.plotly.com/u/hoatran)\
**Post date:** [March 24, 2023, 8:43am UTC](https://community.plotly.com/t/update-layout-versus-callback-for-checklists-and-dropdowns/73827/6 "2023-03-24T08:43:44Z")

</div>

The first method you are talking about is the one that uses dropdown and not a callback right? I think you can change it by using `style={'height':500}` in your dcc.Graph.

```auto
app.layout = html.Div([
    dbc.Row([
        dbc.Col([
            dbc.Checklist(id='my-checklist', options=[{'label':x, 'value':x} for x in df.columns[3:6]],
                          value=df.columns[3],inline=True),
                         dcc.Graph(id='my-line-graph', figure={},style={'height':500})
        ])
    ])
])

```

---

<div class="post-metadata">

**Author:** ![tg550](https://avatars.discourse-cdn.com/v4/letter/t/e9bcb4/32.png) [@tg550](https://community.plotly.com/u/tg550)\
**Post date:** [March 27, 2023, 9:15am UTC](https://community.plotly.com/t/update-layout-versus-callback-for-checklists-and-dropdowns/73827/7 "2023-03-27T09:15:30Z")

</div>

That didn’t work, but adding a specific size to the figure in the px.line section did. Thanks for your help Hoatran, can I ask you to delete the title in the graph of your post though please? Specifically the html.H1 part, its just for my own peace of mind as its work related. Thanks.

---

<div class="post-metadata">

**Author:** ![hoatran](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/hoatran/32/21447_2.png) [@hoatran](https://community.plotly.com/u/hoatran)\
**Post date:** [March 27, 2023, 9:20am UTC](https://community.plotly.com/t/update-layout-versus-callback-for-checklists-and-dropdowns/73827/8 "2023-03-27T09:20:09Z")

</div>

I edited my answer.

---

<div class="post-metadata">

**Author:** ![tg550](https://avatars.discourse-cdn.com/v4/letter/t/e9bcb4/32.png) [@tg550](https://community.plotly.com/u/tg550)\
**Post date:** [March 27, 2023, 3:15pm UTC](https://community.plotly.com/t/update-layout-versus-callback-for-checklists-and-dropdowns/73827/9 "2023-03-27T15:15:46Z")

</div>

Thank you I appreciate it
