I am working on adding a bootstrap collapse element with a leaflet map contained within it so that I can toggle open/close the map view. However, the leaflet map is being sized upon app initialization and does not resize when the collapse item is opened. Therefore, the resulting displayed map when toggled on is mostly just a grey box. After doing some research, it seems that I have to call the invalidateSize function on my map after opening the collapse element. However, I am not sure how to run this javascript command on my Plotly-Dash application. This is what I have currently.
import dash
import dash_bootstrap_components as dbc
import dash_core_components as dcc
import dash_html_components as html
import dash_leaflet as dl
from dash.dependencies import Input, Output, State
map_collapse = dbc.Collapse(
html.Div(
[
dl.Map(
[
dl.TileLayer(),
dl.LocateControl(options={'locateOptions': {'enableHighAccuracy': True}})
],
id="map",
style={'width': '100%', 'height': '50vh', 'margin': "auto", "display": "block"}
)
]
),
id="map-collapse",
is_open=False,
style={
'width': '800px', 'height': '400px'
}
)
collapse_button = dbc.Button(
"Open collapse",
id="collapse-button",
className="mb-3",
color="primary",
n_clicks=0,
)
app.layout = html.Div(
[
collapse_button ,
map_collapse
]
)
@app.callback(
Output("map-collapse", 'is_open'),
[Input("collapse-button", "n_clicks")],
[State("map-collapse", "is_open")]
)
def toggle_collapse(n, is_open):
if n:
return not is_open
return True
if __name__ == '__main__':
app.title = 'Dash App'
app.run_server(debug=True)
Any help will be greatly appreciated!
One possible way to avoid this issue is to delay the (initial) map renderer until the parent container becomes visible. Here is an illustration of how that approach could be implemented for your example,
import dash
import dash_bootstrap_components as dbc
import dash_html_components as html
import dash_leaflet as dl
from dash.dependencies import Input, Output, State
def render_map():
return dl.Map([
dl.TileLayer(),
dl.LocateControl(options={'locateOptions': {'enableHighAccuracy': True}})
], id="map", style={'width': '100%', 'height': '50vh', 'margin': "auto", "display": "block"})
app = dash.Dash(external_stylesheets=[dbc.themes.BOOTSTRAP], prevent_initial_callbacks=True)
map_collapse = dbc.Collapse(id="map-collapse", is_open=False, style={'width': '800px', 'height': '400px'})
collapse_button = dbc.Button(
"Open collapse",
id="collapse-button",
className="mb-3",
color="primary",
n_clicks=0,
)
app.layout = html.Div(
[
collapse_button,
map_collapse
]
)
@app.callback(
Output("map-collapse", 'is_open'),
[Input("collapse-button", "n_clicks")],
[State("map-collapse", "is_open")]
)
def toggle_collapse(_, is_open):
return not is_open
@app.callback(
Output("map-collapse", 'children'),
[Input("map-collapse", "is_open")],
[State("map-collapse", "children")]
)
def render_map_on_show(_, children):
if children is not None:
return dash.no_update
return render_map()
if __name__ == '__main__':
app.title = 'Dash App'
app.run_server()