I’m trying to get dash_deck to accept a predownloaded js variable as its data parameter. I’m populating the js variable with a clientside_callback which fetches a url and puts it in a global called cachelayer. That part is working because if I go in the console I can see the data in that global variable:
I’m then trying to use assign from the javascript module of dash_extensions as the data parameter in a layer. That is failing here
I don’t really know any javascript except to copy-paste things together so I’m hoping this is something simple with promise resolution or maybe I’m just using assign incorrectly. Any help here?
import dash
from dash import Input, Output, State, html, dcc
import dash_deck
import pydeck as pdk
from dash_extensions.javascript import assign, arrow_function
app = dash.Dash(title="client cache test")
app.layout=html.Div([
html.Div([
dcc.Input(id='txtin'),
dbc.Button(id='button', n_clicks=0)],
style={'position': 'absolute', 'top':'0','right':'0', 'z-index':'999'}),
html.Div(id='map', style={'z-index':'998'}),
dcc.Store(id='myout')])
@app.callback(Output('map', 'children'),
Input('txtin', 'value'))
def mappy(txtin):
if txtin == 'wee':
layers=[pdk.Layer(
"GeoJsonLayer",
data=assign("function() {return cachelayer['geo'].resolve();}"),
opacity=0.8,
stroked=False,
filled=True,
extruded=True,
wireframe=True,
get_elevation="properties.valuePerSqm / 20",
get_fill_color="[255, 255, properties.growth * 255]",
get_line_color=[255, 255, 255],
)]
view_state = pdk.ViewState(latitude=49.254, longitude=-123.13, zoom=11, max_zoom=16, pitch=45, bearing=0)
r=pdk.Deck(layers=layers, initial_view_state=view_state, map_style='light')
deck_component=dash_deck.DeckGL(
r.to_json(), id='deck-gl'
)
return deck_component
return "no click"
app.clientside_callback("""
function(clicks, url) {
let layername = 'geo';
if (clicks==0) {
return 'wait';
}
if (typeof(window.cachelayer) == "undefined") {
globalThis.cachelayer={};
globalThis.cachelayer[layername]=fetch(url).then(response=>response.json());
} else {
if (typeof(window.cachelayer[layername]) == "undefined") {
globalThis.cachelayer[layername]=fetch(url).then(response=>response.json());
}
}
return 'wee';
}
""",
Output('txtin','value'),
Input('button', 'n_clicks'),
State('txtin','value')
)
if __name__ == '__main__':
app.run_server(debug=False)
The point of all this is so that the data can be initially loaded on a client then I can add filtering and their browser can do the filtering rather than the server. I don’t want the server to have to load the data in the first place.
Separately, I’ve found this extension which would be better than what I’m trying to do anyways. I’m not sure what the complexity would be to implement this in dash_deck. I see from their github that nothing has been updated in a couple years so I don’t think it’s on anyone’s radar.
Incidentally, I know that dash_leaflet can do the filtering that I’m after but I loaded a couple of my layers in leaflet and the browser just chokes whereas it has no problem with the same layers in deck. Also, deck has native support for heatmaps whereas it seems with dash_leaflet I’d have to generate geotiffs to get heatmaps (maybe I’m wrong here).