Error 'An object was provided as `children` instead of a component....' appears on dashboard

Viewed 426

sample csv data:

date,Data Center,Customer,companyID,source,target,value 6/1/2021,dcA,customer1,companyID1,step1:open_list_view,exit,1 6/1/2021,dcB,customer2,companyID2,step1:open_list_view,exit,1 6/1/2021,dcC,customer3,companyID3,step1:open_list_view,exit,1 6/2/2021,dcD,customer4,companyID4,step1:open_list_view,exit,2 6/2/2021,dcE,customer5,companyID5,step1:open_list_view,step2:switch_display_option,1

I run below code for put the sankey chart in dashboard, and the chart can be updated accordingly by applying filters. but an error appears on dashboard. What is the issue?

An object was provided as children instead of a component, string, or number (or list of those). Check the children property that looks something like:

    import io
from base64 import b64encode
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import plotly.graph_objects as go
import plotly.io as pio
import pandas as pd

external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)

colors = {
    'background': '#111111',
    'text': '#7FDBFF'
}

dataset = pd.read_csv('perfGoal_cleanSankey.csv')

labelListTemp1 = list(set(dataset.source.values))
labelListTemp2 = list(set(dataset.target.values))
labelList = labelListTemp1 + labelListTemp2
sankey_node = list(dict.fromkeys(labelList))
 
fig = go.Figure(data=[go.Sankey( node = dict( pad=15,thickness=20,line = dict(color = "black", width = 0.5),label = labelList,color = 'black' ),
                                 link = dict(source = dataset.source.apply(lambda x: labelList.index(x)),
                                             target = dataset.target.apply(lambda x: labelList.index(x)),
                                             value = dataset.value))])

#fig.update_layout(autosize=False,width = 3000,height = 1000,hovermode = 'x',title="performance Goal user behavior monitor",font=dict(size=16, color='blue'))
    
#fig.write_html('/Users/i073341/Desktop/plotly/perfUXRGoal.html', auto_open=True)
#fig.show()



app.layout = html.Div([
    dcc.Dropdown(
        id='dataCenter_dropdown',
        options=[ {'label': i, 'value': i} for i in dataset['Data Center'].unique()] + [{'label': 'Select all', 'value': 'allID'}],
        multi=True, placeholder='Please select Data Center'),
    dcc.Dropdown(
        id='customer_dropdown',
        options=[{'label': i, 'value': i} for i in dataset['Customer'].unique()]  + [{'label': 'Select all', 'value': 'allID'}],
        multi=True, placeholder='Please select Customer'),
    
    dcc.Dropdown(
        id='companyID_dropdown',
        options=[{'label': i, 'value': i} for i in dataset['companyID'].unique()] + [{'label': 'Select all', 'value': 'allID'}],
        multi=True, placeholder='Please select companyID'),
    
    
#    html.Div(id='dd-output-container'),
     dcc.Graph(id='uxrPerfGoalSankey',figure=fig)
])

@app.callback(
#    Output('dd-output-container', 'children'),
    Output('uxrPerfGoalSankey', 'figure'),
    [Input('dataCenter_dropdown', 'value'),
     Input('customer_dropdown', 'value'),
     Input('companyID_dropdown', 'value')])


def update_graph(dataCenter, customer, companyID):

    if dataCenter=='Select all' and customer=='Select all' and companyID=='Select all':
        df=dataset.copy()
    else:
        df = dataset.loc[dataset['Data Center'].isin([dataCenter]) & dataset['Customer'].isin([customer]) & dataset['companyID'].isin([companyID])]
    
    labelListTemp1 = list(set(df.source.values))
    labelListTemp2 = list(set(df.target.values))
    labelList = labelListTemp1 + labelListTemp2
    sankey_node = list(dict.fromkeys(labelList))
    
    fig = go.Figure(data=[go.Sankey( node = dict( pad=15,thickness=20,line = dict(color = "black", width = 0.5),label = labelList,color = "blue" ),
                                     link = dict(source = df.source.apply(lambda x: labelList.index(x)),
                                                 target = df.target.apply(lambda x: labelList.index(x)),
                                                 value = df.value))])
    return fig
    
    

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

Your callback function returns a figure and is trying to assign it to the children property of a html.Div. Can't do that as far as I know. A div's child should be other components, strings or numbers as stated in the error message.

Did you mean to write

Output('uxrPerfGoalSankey', 'figure'),

instead?

If not and you need to return a new fig to that div, create a dcc.Graph inside your div and return that graphs's figure value instead.

Edit:

You also overwrite your input values right at the top of your callback function. No matter what you select, the df is ultimately filtered by the same values. I.E. you select dataCenter 'A' in your dropdown but in the first line you set dataCenter to dataframe['Data Center'], so what was the point of selecting one? If that's not intended, delete those assignments?

One imminent pitfall by the way: multi dropdowns pass either a single value or a list of values. To make your df selection consistent, force all the inputs to be lists:

if not isinstance(dataCenter, list):
    dataCenter = [dataCenter]
# etc

Edit 2:

The issue was how you handle the parameters being lists vs single values and the selection of 'select all'. I adjusted the logic to treat 'None' (dd selection empty) and 'Select all' as all values selected. If you don't want to plot anything when a selection is empty, do this instead:

from dash.exceptions import PreventUpdate

...

And then first thing in your callback function:

if dataCenter is None or customer is None or companyID is None:
    raise PreventUpdate

Anyway here's the code with the logic as I described it:

import dash
import dash_core_components as dcc
import dash_html_components as html
import pandas as pd
import plotly.graph_objects as go
from dash.dependencies import Input, Output

from dash.exceptions import PreventUpdate

external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)

colors = {
    'background': '#111111',
    'text': '#7FDBFF'
}

dataset = pd.read_csv('values.csv')


def generate_graph(df):

    labels = list(set(df.source.values)) + list(set(df.target.values))

    fig = go.Figure(data=[
        go.Sankey(node=dict(pad=15, thickness=20, line=dict(color="black", width=0.5), label=labels, color="blue"),
                  link=dict(source=df.source.apply(lambda x: labels.index(x)),
                            target=df.target.apply(lambda x: labels.index(x)),
                            value=df.value))
    ])

    return fig


app.layout = html.Div([
    dcc.Dropdown(
        id='dataCenter_dropdown',
        options=[{'label': i, 'value': i} for i in dataset['Data Center'].unique()] + [
            {'label': 'Select all', 'value': 'allID'}],
        multi=True, placeholder='Please select Data Center'),
    dcc.Dropdown(
        id='customer_dropdown',
        options=[{'label': i, 'value': i} for i in dataset['Customer'].unique()] + [
            {'label': 'Select all', 'value': 'allID'}],
        multi=True, placeholder='Please select Customer'),

    dcc.Dropdown(
        id='companyID_dropdown',
        options=[{'label': i, 'value': i} for i in dataset['companyID'].unique()] + [
            {'label': 'Select all', 'value': 'allID'}],
        multi=True, placeholder='Please select companyID'),

    dcc.Graph(id='uxrPerfGoalSankey', figure=generate_graph(dataset))
])


@app.callback(
    Output('uxrPerfGoalSankey', 'figure'),
    [Input('dataCenter_dropdown', 'value'),
     Input('customer_dropdown', 'value'),
     Input('companyID_dropdown', 'value')])
def update_graph(dataCenter, customer, companyID):

    if dataCenter is None or len(dataCenter) == 0 or 'allID' in dataCenter:
        dataCenter = dataset['Data Center']
    elif not isinstance(dataCenter, list):
        dataCenter = [dataCenter]

    if customer is None or len(customer) == 0 or 'allID' in customer:
        customer = dataset['Customer']
    elif not isinstance(customer, list):
        customer = [customer]

    if companyID is None or len(companyID) == 0 or 'allID' in companyID:
        companyID = dataset['companyID']
    elif not isinstance(companyID, list):
        companyID = [companyID]

    df = dataset[
        (dataset['Data Center'].isin(dataCenter)) &
        (dataset['Customer'].isin(customer)) &
        (dataset['companyID'].isin(companyID))
        ]

    return generate_graph(df)


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

Runs fine for me, let me know if any other issues arise.

Related