Hi,
I’m trying to create graphs dynamically. Basically, I load some json data from a server and I want to make a LOT of graphs out of it (I want to split them up by dropdowns and pages later but for now we have at least 2,000 we are looking at. I’m planning to allow the user to search by name later).
I get the data from an API which gives it to me all at once, so I’m forced to wait for the data, but I want the user to see a blank graph of all the graphs that are being created/loading this data. I don’t want them all to be forced to load at once (making the user wait quite a long time). Is there a way I can break up this data over a loop and create these graphs dynamically with callbacks? The graph-creating process is slow enough that lazy loading them seems like a good idea.
So far I’m trying this:
app.config['suppress_callback_exceptions']=True
app.layout = html.Div([
html.H1(children='Web Metrics for ArcGIS Usage at ----', style={
'textAlign': 'center'
}),
dcc.Tabs(id="tabs", value="online", children=[
dcc.Tab(label='ArcGIS Online', value="online"),
dcc.Tab(label='ArcGIS Enterprise', value="enterprise"),
], className="four columns"),
html.Div([
dcc.Dropdown(
options=[
{'label': 'Maps', 'value': 'maps'},
{'label': 'Apps', 'value': 'apps'},
{'label': 'Layers', 'value': 'layers'},
{'label': 'Tools', 'value': 'tools'},
{'label': 'Data Files', 'value': 'files'},
{'label': 'All', 'value': 'all'}
],
value='maps'
)
]
),
html.Div(id="loaded", children=html.H1("loaded"), style={'display':'none'}),
#dcc.Loading(id="loadingOnline", children=[html.Div(id="loading-output-online")], type="default"),
html.Div(id='dataLoadedSignal',
style={'display':'none'}),
html.Div(id="onlineGraphs", style={'display':'none'}), #Layout for adding online graphs later
html.Div(id="nothing", style={'display':'none'})
])
@app.callback(Output('dataLoadedSignal', 'children'),
[Input('loaded', 'children')])
def load(something):
print("data loaded")
return getData("url",
getCreds('arcgisOnlineUsername'), getCreds('arcgisOnlinePassword'))
@app.callback(Output('nothing', 'children'),
[Input('dataLoadedSignal', 'children')],
)
def drawLayout(data):
#generate the layout graphs & their callbacks
print('draw layout')
count = 0
for i in data:
try:
@app.callback(Output(i['id'] + "_graph", 'children'),[
Input('dataLoadedSignal', 'children'),
])
def createGraph(data):
return html.Div(html.H3("hello"))
#Give it another callback to populate the data
# @app.callback(Output(i['id'] + "_graph", 'children'), [
# Input(i['id'] + "_graph", 'children'),
# ])
# def graph_update(i):
# print("calling graph usage")
# return graphItemUsage(i, 'Date', 'Views', "Item Usage ArcGIS Online", "four columns")
except (TypeError, RuntimeError) as e:
print("No usage data for: ")
print(i)
print(e)
count += 1
print("layout complete")
return html.Div()
I have no way to pass an index (i) so it knows what data to load from the data I’ve downloaded. Am I going about this wrong? And I keep getting this error:
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: