0

I am a begginer with Dash. I tried to make an interactive application which retrieve a list of public companies for a given city, then to display them in a DashTable and in DashLeaflet map with markers.

I have an input filled by user (the city), and I retrieve the list of companies with open data API, geocode them, and display them in dashtable and in the map.

def get_markers(df):
    markers = []
    for i in range(len(df)):
        markers.append(
            dl.Marker(
                id=df.loc[i,"siret"],
                draggable=True,
                title=df.loc[i, "siret"],
                position=(df.loc[i, "lat"], df.loc[i, "lon"]),
                children=[dl.Tooltip(df.loc[i, :]),
                          dl.Popup(df.loc[i, "enseigneEtablissement"])]
                ))                            
    return markers


app = dash.Dash(__name__, serve_locally=False)
app.layout = html.Div(children=[
    html.H1(children='Hello Dash'),

    dcc.Store(id='clientside-store'),
       
    dl.Map([dl.TileLayer()],
           id="map",
           center=[39, -98],
           zoom=4,
           style={'width': '1000px', 'height': '500px'}),
          
    dcc.Input(id="input", type="text", placeholder="n°SIREN", value=''),
    html.Button('Rechercher les établissements', id='button'),
       
    dash.dash_table.DataTable(id='dashTable')

])


@app.callback(Output('clientside-store', 'data'),
            [Input(component_id='button', component_property='n_clicks')],
            [State(component_id='input', component_property='value')]
)            
def update_table(n_clicks, input_value):
    if n_clicks is not None:
        df = getEtablissements(input_value)     
        return df.to_dict(orient='records')
    else:
        return dash.no_update


@app.callback(Output("map", "children"),
              Output("dashTable", "data"),
              Output("dashTable", "columns"),
              Input('clientside-store', 'data'))
def store_to_map_n_table(store_data):
    df = pd.DataFrame(store_data)
    columns = [{'name': col, 'id': col} for col in df.columns]     
    return [dl.TileLayer()] + get_markers(df), df.to_dict(orient='records'), columns


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

example display

After that, I want to make editable marker in the map. The user could move the marker and stock the new location.

I already have a script to get the new location after a drag and drop of markers:

# Marker location updating
@app.callback(Output('clientside-store', 'data'), 
              dict(positions = [Input(lbl, "position") for lbl in **'data'**.siret]),
              State('clientside-store', 'data'),
              prevent_initial_call=True)
def update_store_data(positions, data):
    df = pd.DataFrame(data)
    marker_id_clicked = dash.callback_context.triggered[0]['prop_id'].split('.')[0]
    location = dash.callback_context.inputs[marker_id_clicked + '.position']
    df.loc[df['id'] == marker_id_clicked, 'lat'] = location[0]
    df.loc[df['id'] == marker_id_clicked, 'lon'] = location[1]
    return df.to_dict('records')

I have to use the existing data in DashStore, to create the inputs for each Markers. And finally return the new location in the DashStore. Resume, I have two problems :

  • make two call back with the same output : DashStore data
  • use dynamic DashStore data as inputs of callback
Srn
  • 1
  • 1

0 Answers0