5
votes

I'm creating a web app using plotly dash for graph generation and callback handling. I use dash-core-components v0.18.1

When trying to add graphs dynamically (each time a button is clicked, a new graph is added), an error appears in the console:

bundle.js?v=0.11.2:9 Uncaught (in promise) Error: dash_core_components was not found. at Object.resolve (bundle.js?v=0.11.2:9) at s (bundle.js?v=0.11.2:9) at Array.map () at s (bundle.js?v=0.11.2:9) at Array.map () at s (bundle.js?v=0.11.2:9) at Array.map () at s (bundle.js?v=0.11.2:9) at e.value (bundle.js?v=0.11.2:9) at p._renderValidatedComponentWithoutOwnerOrContext ([email protected]?v=0.11.2:13)

I just have a blank page with a button and a callback on click. The callback simply fills a div with a graph.

Layout code:

class ContentController(object):

    graph_names = None

    def __init__(self):
        self.graph_names = []
        # UNCOMMENT THIS LINE TO MAKE IT WORK
        # self.graph_names = ["start_graph"]

    def layout(self):
        return html.Div([html.Button("Add Graph", id='button_id'),
                         html.Div(self.graphics_layout, id='graphics_div')],
                        id='main_div')

    @property
    def graphics_layout(self):
        graphs = []
        for name in self.graph_names:
            graph = self.create_graph()
            graphs.append(dcc.Graph(id=name, figure=graph, style=    {'width': '600px', 'height': '300px'}))

        return graphs

    def create_graph(self):
        graph_data = {
               'data': [
                   {'x': [1, 2, 3], 'y': [4, 1, 2], 'type': 'bar',     'name': 'SF'},
                   {'x': [1, 2, 3], 'y': [2, 4, 5], 'type': 'bar',     'name': u'Montréal'},
               ],
               'layout': {
                   'title': 'Dash Data Visualization'
               }
           }
        return graph_data

Callback Code

@app.callback(
    Output(component_id='graphics_div', component_property='children'),
    [Input(component_id='button_id', component_property='n_clicks')]
)
def callback_function(n_clicks):
    print(n_clicks)
    if n_clicks is None:
        return ""

    name = "graph_" + str(n_clicks)
    content.graph_names.append(name)
    return content.graphics_layout

The weird thing is that if another graph is present when loading the page, then everything works fine. Is this a bug in Dash?

1
hi, i'm trying to do something similar to this in that I want to render a new graph whenever a radio button is clicked, could you point me in the right direction towards an example of this being done.. or perhaps how you learned to do it yourself? thank you - JAbrams
Note that this flaw has been fixed as of November 2018 (see this issue), so the hidden Div workaround from the accepted answer is not needed anymore. - Michel

1 Answers

5
votes

It turns out that this is a flaw in Dash.

Workaround: Create a hidden graph on load like this:

app.layout = html.Div([
    html.Div(id='content'),
    dcc.Location(id='location', refresh=False),
    html.Div(dt.DataTable(rows=[{}]), style={‘display’: ‘none’})
])

The reason is that the needed libraries are only loaded when the page loads, so if no graph are present in the layout at load time, some dash libraries will not be loaded.

More information can be found on the dash issue board: Here and Here