Using dcc.Loading with a callback running a sql query

I’d like to use dcc.Loading with a callback that is running an sql query based on user input. I am thinking of a spinner pop-up when the query is running and processing the result.

https://dash.plotly.com/dash-core-components/loading

Here’s a simplified / minimal example for Illustration:

import dash
from dash.dependencies import Input, Output, State
from dash import dcc, html
import dash_bootstrap_components as dbc
import pandas 
import numpy 
import mapbox
from app import app

# Mapbox
MAPBOX_KEY="pk.xxxxxxx"
token = MAPBOX_KEY
Geocoder = mapbox.Geocoder(access_token=token)

# mysql connection
import pymysql
from sqlalchemy import create_engine
user = 'user1'
pwd = 'xxxx'
host =  'xasdas'
port = 3306
database = 'main'
engine = create_engine("mysql+pymysql://{}:{}@{}/{}".format(user,pwd,host,database))
con = engine.connect()

layout = html.Div([ 
                                   dcc.Input( id = "selection", type = "search", list = "list1" ) , 
 
                                   dcc.Graph(id="map1"),

                ])

app.callback([ 
                          Output("map". "figure")
                       ],
                       [
                          Input("selection","value")
                       ]
def update_map(selection):

      data = []
 
       if selection:
          
           query = '''
                          select x, y, z
                          from table1
                          where val = {}
                         '''.format(selection)

            df = pd.read_sql(query, con)

            data.append({

                        "type": "scattermapbox",
                        "lat": df['x'],
                        "lon": df['y'],
                        "name": "Location",
                        "hovertext": propname,
                        "mode": "markers",
                        "clickmode": "event+select",
                        "marker": {
                            "autocolorscale": False,
                            "showscale":True,
                            "symbol": "circle",
                            "size": 9,
                            "opacity": 0.8,
                            "color": df['z'],
                            }
                     }
            )

       layout = {

                 "autosize": True,
                 "hovermode": "closest",
                 "mapbox": {

                     "accesstoken": MAPBOX_KEY,
                     "bearing": 0,
                     "center": {
                         "lat": x,
                         "lon": y
                     },
                     "pitch": 0,
                     "zoom": zoom,
                     "style": "streets",

                 },

                 "margin": {
                    "r": 0,
                    "t": 0,
                    "l": 0,
                    "b": 0,
                    "pad": 0
                }

    } 

   return ({"data": data, "layout": layout})

This query could take a long time due to large volume of data, indices etc. to populate data list and update the map layout. For better UX, how do I use the dcc.Loading component while the query is running and processing the data?

Just wrap it around the dcc.Graph component:

dcc.Loading(
    id="loading-1",
    type="default",
    children=dcc.Graph(id="map1")
)

Note that there are two typos in your callback, it should be

Output("map1", "figure")

instead of

Output("map". "figure")
1 Like

Is there a way to center the loading spinner? At the minute, it appears on top left of the screen.

You can define custom CSS styling to the dcc.Loading component by setting the parent_style property. If you don’t want the CSS hassle, you could also use the LoadingOverlay of Dash Mantine Components:

It centers the Loader over the given container (in your case the dcc.Graph container).

1 Like