Hello,
I’ve been checking that the dashboards I have written for Dash in Python, and were running smoothly in older version of Dash, still run smoothly when I upgrade to Dash 1.0.0. And this is where I’m having an error that I can’t fully understand.
I have a dropdown menu with a list of countries (also includes a global option to plot all data in a scatter plot). I have been asked to setup the graph, so that you can navigate via selecting the country from the dropdown list or by click on a country point within the global view, which triggers a callback to update the dropdown value.
If I select the country via the dropdown list, the graph updates fine, and then click within the second graph (which is a pie chart) it default back to the global view. But when I click on a point in the global view, I get the code to update the dropdown value, then get the following error,
This error originated from the built-in JavaScript code that runs Dash apps. Click to see the full stack trace or open your browser’s console.
Looking at the print statements I put into my code, the update_graph function is running to the end and returning the new graph. So I can’t understand why it plots fine one way and not the other.
example code that causes the error
import numpy as np
import dash
import dash_core_components as dcc
import dash_html_components as html
import plotly.graph_objs as go
from dash.dependencies import Input, Output
app = dash.Dash()
key_cols = {'a': '#2eb2ff',
'b': '#ffbe15',
'c': '#42f042',
'd': '#ff3a3c',
'e': '#de9aff',
'f': '#d28170',
'g': '#ffb2ff',
'h': '#bebebe',
'i': '#ffff33',
'total': '#22ffff'}
countries = [
'Australia',
'Austria',
'Belgium',
'Czech Republic',
'Denmark',
'Finland',
'France',
'Germany',
'Ireland',
'Italy',
'Netherlands',
'Nigeria',
'Norway',
'Poland',
'Portugal',
'Spain',
'Sweden',
'Switzerland',
'United Kingdom',
'United States']
# test data
data = {}
for country in countries:
data[country] = {}
for key in key_cols:
data[country][key] = np.random.randint(10000000)
data[country]['total'] = sum(data[country].values())
app.layout = html.Div([
html.H2('test'),
# inputs for plot selection
html.Div([
# region
html.Div([
html.Div([
html.Label('Select region: ')
]),
html.Div([
dcc.Dropdown(
id='dropdown-country',
options=[{'label': 'Global', 'value': 'Global'}] +
[{'label': v, 'value': v} for v in countries],
value='Global'
),
], style = {'display': 'inline-block','vertical-align': 'top', 'width': '250px'})
], style = {'display': 'inline-block', 'width': '250px'}),
]),
# plot graph
html.Div([dcc.Graph(id='graph1')])
])
# ------------------------------------------------------------------------------
# updates count plots & options for the region dropdown
@app.callback(
Output('dropdown-country', 'value'),
[Input('graph1', 'clickData')])
def update_value(clickData):
try:
country = clickData['points'][0]['y'].replace('<br>', ' ')
except:
country = 'Global'
return country
# ------------------------------------------------------------------------------
@app.callback(
Output('graph1', 'figure'),
[Input('dropdown-country', 'value')])
def update_graph1(dropVal):
print(dropVal)
# if no clickView, set to global view
if not dropVal:
dropVal = 'Global'
# if not global view plot pie of tablename counts
if dropVal == 'Global':
# prepare global data view
scatterData = {}
scatterData['x'] = []
scatterData['y'] = []
scatterData['count'] = []
scatterData['text'] = []
scatterData['colours'] = []
for country in countries:
for key, val in data[country].items():
# adding key name
scatterData['x'].append(key)
# adding country name with line break for better style
scatterData['y'].append(country.replace(' ', '<br>'))
# add count
scatterData['count'].append(val)
# add colour
scatterData['colours'].append(key_cols[key])
# hover over text data
msg = '{}<br>{}<br>{} Products'
textVal = msg.format(key, country, val)
scatterData['text'].append(textVal)
sizeRef = 500000000/(1e5*50**2)
size = [np.sqrt(s) for s in scatterData['count']]
# add scatter plot
plotData = [
go.Scatter(
x=scatterData['x'],
y=scatterData['y'],
mode='markers',
marker={
'size': size,
'color': scatterData['colours'],
'sizemode':'area',
'sizeref': sizeRef,
'sizemin': 3
},
hoverinfo = 'text',
text=scatterData['text']
)
]
# offset plot to allow space for table plot & set x-axis properties
xaxisLayout={
'domain':[0, 0.8],
'title': 'Data Feed',
'autorange': False,
'range':[-1, len(key_cols)]}
# set y-axis properties
yaxisLayout={
'title': 'Country',
'autorange': False,
'range': [-1, len(countries)]
}
# delete prepared data after plots created
del scatterData
else:
# prepare country pie chart
pieData = {}
pieData['labels'] = []
pieData['values'] = []
pieData['colours'] = []
for key, val in data[dropVal].items():
if key == 'total':
continue
pieData['labels'].append(key)
pieData['values'].append(val)
pieData['colours'].append(key_cols[key])
# add pie chart
plotData = [
go.Pie(
labels=pieData['labels'],
values=pieData['values'],
hoverinfo='label+value+percent',
textinfo='label+percent',
textfont={'size':15, 'color':'#000000'},
rotation=135,
marker={'colors': pieData['colours']}
)
]
# offset plot to allow space for table plot
xaxisLayout={'domain':[0, 0.8]}
yaxisLayout={}
# delete prepared data after plots created
del pieData
return {
'data': plotData,
'layout': {
'title': '{} Data'.format(dropVal),
'font': {'color':'#e6e6e6'},
'plot_bgcolor': '#444444',
'paper_bgcolor': '#444444',
'margin': {'l': 70, 'b': 40, 't': 40, 'r': 10},
'showlegend': False,
'hovermode': 'closest',
'height': 1000,
'xaxis': xaxisLayout,
'yaxis': yaxisLayout
}
}
if __name__ == '__main__':
app.run_server(debug=True)
full stack trace
[614]</r.hover/<@http://127.0.0.1:8050/_dash-component-suites/dash_core_components/plotly-1.47.0.min.js?v=0.47.0&m=1562667246:7:1890578
l@http://127.0.0.1:8050/_dash-component-suites/dash_core_components/plotly-1.47.0.min.js?v=0.47.0&m=1562667246:7:2082697
[726]</r.throttle@http://127.0.0.1:8050/_dash-component-suites/dash_core_components/plotly-1.47.0.min.js?v=0.47.0&m=1562667246:7:2082768
[614]</r.hover@http://127.0.0.1:8050/_dash-component-suites/dash_core_components/plotly-1.47.0.min.js?v=0.47.0&m=1562667246:7:1883718
[758]</r.initInteractions/</u.onmousemove/t._fullLayout._rehover@http://127.0.0.1:8050/_dash-component-suites/dash_core_components/plotly-1.47.0.min.js?v=0.47.0&m=1562667246:7:2233789
[810]</v.rehover@http://127.0.0.1:8050/_dash-component-suites/dash_core_components/plotly-1.47.0.min.js?v=0.47.0&m=1562667246:7:2409710
[701]</l.syncOrAsync@http://127.0.0.1:8050/_dash-component-suites/dash_core_components/plotly-1.47.0.min.js?v=0.47.0&m=1562667246:7:2050079
[736]</r.plot@http://127.0.0.1:8050/_dash-component-suites/dash_core_components/plotly-1.47.0.min.js?v=0.47.0&m=1562667246:7:2113330
[701]</l.syncOrAsync@http://127.0.0.1:8050/_dash-component-suites/dash_core_components/plotly-1.47.0.min.js?v=0.47.0&m=1562667246:7:2050079
[736]</r.react@http://127.0.0.1:8050/_dash-component-suites/dash_core_components/plotly-1.47.0.min.js?v=0.47.0&m=1562667246:7:2132164
plot@http://127.0.0.1:8050/_dash-component-suites/dash_core_components/dash_core_components.dev.js?v=0.47.0&m=1562667246:124549:21
componentWillReceiveProps@http://127.0.0.1:8050/_dash-component-suites/dash_core_components/dash_core_components.dev.js?v=0.47.0&m=1562667246:124700:14
Zf@http://127.0.0.1:8050/_dash-component-suites/dash_renderer/react-dom@16.8.6.min.js?v=0.23.0&m=1562667244:67:370
qg@http://127.0.0.1:8050/_dash-component-suites/dash_renderer/react-dom@16.8.6.min.js?v=0.23.0&m=1562667244:95:336
hi@http://127.0.0.1:8050/_dash-component-suites/dash_renderer/react-dom@16.8.6.min.js?v=0.23.0&m=1562667244:104:285
Qg@http://127.0.0.1:8050/_dash-component-suites/dash_renderer/react-dom@16.8.6.min.js?v=0.23.0&m=1562667244:144:293
Rg@http://127.0.0.1:8050/_dash-component-suites/dash_renderer/react-dom@16.8.6.min.js?v=0.23.0&m=1562667244:145:168
Sc@http://127.0.0.1:8050/_dash-component-suites/dash_renderer/react-dom@16.8.6.min.js?v=0.23.0&m=1562667244:158:109
Z@http://127.0.0.1:8050/_dash-component-suites/dash_renderer/react-dom@16.8.6.min.js?v=0.23.0&m=1562667244:156:492
Kc@http://127.0.0.1:8050/_dash-component-suites/dash_renderer/react-dom@16.8.6.min.js?v=0.23.0&m=1562667244:155:69
ya@http://127.0.0.1:8050/_dash-component-suites/dash_renderer/react-dom@16.8.6.min.js?v=0.23.0&m=1562667244:153:185
enqueueSetState@http://127.0.0.1:8050/_dash-component-suites/dash_renderer/react-dom@16.8.6.min.js?v=0.23.0&m=1562667244:202:409
t.prototype.setState@http://127.0.0.1:8050/_dash-component-suites/dash_renderer/react@16.8.6.min.js?v=0.23.0&m=1562667244:20:433
handleChange@http://127.0.0.1:8050/_dash-component-suites/dash_renderer/dash_renderer.dev.js?v=0.23.0&m=1562667244:33404:14
dispatch@http://127.0.0.1:8050/_dash-component-suites/dash_renderer/dash_renderer.dev.js?v=0.23.0&m=1562667244:34404:7
createThunkMiddleware/</</<@http://127.0.0.1:8050/_dash-component-suites/dash_renderer/dash_renderer.dev.js?v=0.23.0&m=1562667244:33892:16
dispatch@http://127.0.0.1:8050/_dash-component-suites/dash_renderer/dash_renderer.dev.js?v=0.23.0&m=1562667244:33950:18
handleResponse@http://127.0.0.1:8050/_dash-component-suites/dash_renderer/dash_renderer.dev.js?v=0.23.0&m=1562667244:38435:17
handleJson@http://127.0.0.1:8050/_dash-component-suites/dash_renderer/dash_renderer.dev.js?v=0.23.0&m=1562667244:38552:17
Any thoughts? Thanks in advance.