Using a js global variable for the data of dash_deck layers OR implement deck.gl extension

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:
image

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).

Hello @Deanm0000,

Welcome to the community!

For this, you’ll need to have a clientside callback that’s output is the figure, in which you will need to update the data as is available in your js.

You’ll need to add an id to the layer, then you should be able to target the data prop of it. :slight_smile:

I havent used dash_deck, but as long as the component is registered with dash, you should be able to target the props accordingly.