Charts Template - Custom Mapbox Visualization Isn't Working

While the built-in Mapbox viewer is quite handy, we’re looking to do more than it allows. For that reason we’re looking to potentially add a custom Mapbox or Leaflet component.

The Charts template had an example of a custom Mapbox viewer (see the third tab), but it’s currently broken. Would it be possible to get that fixed?

While I’m thinking of it, do you happen to have any other examples of custom mapping components that you could be share? We’re really enjoying Retool, but having some more examples to look at would be great.

Hey there @geospatial and welcome to the community!!

The Mapbox part of the chart template seems to be working fine for me - what issue are you seeing on your end? Any chance you’d be able to reply to this with a screenshot?

I’ll ping the team to see if we can find more examples. Have you seen our USA map template?

Ah, it's a Safari problem. We just tried on a couple of different Macs and an iPhone and it's happening on all of them. The Macs have Safari 13.0.4 on them, and the iPhone has iOS 13.5 on it. If I open the same page in Chrome it works properly.

Yup, we've seen the USA map template. It was very useful in helping us get the built-in Mapbox viewer working in our custom Retool app. Unfortunately we've had trouble programmatically setting the latitude/longitude of the built-in Mapbox viewer, hence our looking at potential workarounds.

For what it's worth, we did have some success with the built-in Mapbox viewer, by:

  • Creating two Temporary States (MapLat and MapLong)
  • Settings their values based on Map.viewport.latitude and Map.viewport.longitude through a JS query that triggers when the map pans
  • Setting the map's Latitude and Longitude parameters in the Retool UI to {{MapLat.value}} and {{MapLong.value}}
  • Then, if we set the MapLat and MapLong Temporary state values, the map itself will pan to that location.

The problem is that some times the map will 'stutter' on pan as a result of this setup, since MapLat and MapLong haven't caught up to Map.viewport.latitude and Map.viewport.longitude but the map is grabbing those values to set it's own latitude and longitude.

What does that workflow look like? It sounds like this is to make it possible to set the centerpoint of the view, why does the value of the temp state need to continuously update? The Latitude and Longitude settings in the map are just the default/initial value. Each time they update, the map will snap to that spot but otherwise you can pan the map freely.

Re: our workflow, that’s correct @alex-w. We have a search field that populates a table, then when you click on a table entry the map jumps to a particular latitude, longitude and zoom level.

Your solution is the approach we took first, but we found were unable to set those values. Perhaps it’s just a lack of JS knowledge on our part?

What we tried was: when a row is clicked in the table, we fire a JS query. We were unsure if we need to set the lat/long/zoom values on the Mapbox itself (e.g. Map.latitude = 46) or on it’s viewport (e.g. Map.viewport.latitude = 46), but when the query fires nothing happens.

Just following up on this =)

@alex-w @justin any updates?

Hi @geospatial! Would you mind messaging in on intercom (the blue chat icon) with permission for us to open your app on our end and check it out?

Ok, after going over this with @geospatial it looks like the issue was due to some nuances with the settings:

  • Setting the latitude and longitude values of a map to temporary state variables will let you use .setValue() on them to change the view of the map, where the map component itself doesn’t directly support any .setValue type methods.
  • Those properties are essentially default values that function the same as default values on other retool components. Whenever the reference updates, the default value will populate the component’s settings. After that, you can change the value (in this case by panning the map) and the default value will remain the same whereas the live component values will always match the input.
  • After changing the values, you can reference map.latitude and map.longitude to get their current values, rather than tempState.value which would be the previous default values.

Oh also @geospatial- one piece of advice I thought of after we looked through the app. You can set the value of a single temp state rather than many using something like tempState.setValue({latitude: lat, longitude:long, option: “foobar”}) and so on, and then in different places reference individual selections like {{tempState.value.latitude}}. Then you can also use the .setIn() method on the temp state to change/create new key values inside the object or inside specific index/key combinations to update individual values without rewriting the whole value.