I am trying to update the coordinates of a folium map rendered by a Dash App on a callback (which is running inside a Flask App). The callback selectively renders different layers on a map - the issue is that the zoom and center coordinates are not persisted when the map is updated. The map is rendered as html and injected as in iframe into the app.
Addendum: Not a professional programmer, have only been trying my hand at this for the past six months.
I have tried three approaches:
- JS API call client-side to flask route. I ended up realizing this had too much overhead (plus couldnāt identify user to update the proper coordinates).
- Encoding the coordinates and zoom in the URL. The URL changes as expected from this js snippet:
map_layer.on("mouseup zoomend", function(){
var coordinates = map_layer.getCenter();
var lat = coordinates.lat
var lon = coordinates.lng
var zoom = map_layer.getZoom();
parent.history.replaceState({}, '', `/app/layer?&lat=${lat}&lon=${lon}&zoom=${zoom}`);
// const ON_CHANGE = '_dashprivate_historychange';
// window.dispatchEvent(new CustomEvent(ON_CHANGE));
// parent.window.dispatchEvent(new CustomEvent(ON_CHANGE));
console.log("success");
The commented-out code also tries to dispatch a CustomEvent to dash to try and update itās history - not really clear whatās happening there - just tried to emulate this approach.
The right URL is not passed on to the callback however. So despite the url changing on the browser, itās not being sent back with the updated query variables. If I refresh the page and actively send the URL, than the right URL is passed on, but thatās not the kind of behavior Iām looking for - I would like for it to change with no active reloading of the page:
@layer.callback(
Output("map", "srcDoc"),
-- other inputs --,
Input('url', 'href') #tried State as well
)
def update_output_src(href):
print(href)
-- other code --
return map.get_root().render()
- Using a hidden DIV to store the coordinates . The div content changes as expected from this js snippet:
map_layer.on("mouseup zoomend", function(){
var coordinates = map_layer.getCenter();
var lat = coordinates.lat
var lon = coordinates.lng
var zoom = map_layer.getZoom();
var latstore = parent.document.getElementById('latstore');
latstore.textContent = lat; #trying different approaches in what's changed to see if dash callback captures it.
var lonstore = parent.document.getElementById('lonstore');
lonstore.innerText = lon;
var zoomstore = parent.document.getElementById('zoomstore');
zoomstore.innerHTML = zoom;
console.log("success");
But again I am not able to capture the stored coordinates when the input is triggered.
@layer.callback(
Output("map", "srcDoc"),
-- other inputs --,
State('latstore', 'children'),
State('lonstore', 'children'),
State('zoomstore', 'children'),
)
def update_output_src(latstore, lonstore, zoomstore):
print(latstore, lonstore, zoomstor)
-- other code --
return map.get_root().render()
Any help or pointer in the right direction for approaches 2 or 3 would be super useful. I have been struggling with this for 3-4 days now and Iām out of ideas.