Skip to main content

Map view (Lesson 4.11)

Now that we can save our user’s location, lets learn how to visualize those locations on a map!

Sofia Maconi avatar
Written by Sofia Maconi
Updated over 2 weeks ago

Transcript

So now that our users can add a location to their diary entries, it makes sense that we allow them to view their diary entries on a map and even click on one of the map markers in order to view the associated diary entry.

So that’s what we’re going to build in this lesson.

Very excitingly, the first thing that we’re going to do is create an entirely new tab view. This is going to be the view that holds our map. And because the map is just going to take up the entire height of the user’s screen, we’re going to make it not scrollable.

Right away, let’s set this up as a tab. We’re going to include it as a tab item — that’s going to then add one new tab to our tab bar. I actually want this to be in the middle here, and we can set it right away to our tab style that we created earlier in the course so it matches the styling of our other tabs.

Let’s update the label and the icon as well. We’re going to go into our Phosphor library, which we’ve been using throughout the course, and we could use any of these icons. I think this one is the most appropriate.

Just like for our other tab items, we’ve got a condition that says when the tab item is selected, we’re going to use a filled version of the icon. So I’m going to do the same thing here for our map icon — change it to the filled version like so.

Right away you can see that we can go to our new map view. Brilliant.

So let’s add our map now. The map is actually a visual element that we can add to the page. The first thing I’m going to do is change the layout settings. We’ve got a fixed height for this map — I’m going to turn that off so it extends the full height of the viewport.

Now, if we test this out and try to load our map, you’ll notice that we get an error saying we’re missing our Google Maps key. This key is something that we need in order for the map element to function properly.

This is actually a Google Maps element, and as such, we need to have an API key in order to access it. There’s an article in Bubble’s documentation about how to set these keys up, which I’ll link to in the description for this video.

When you’ve got your key, go under Settings → General, and if you scroll down, there’s a section that lets you add your API key for both iOS and Android.

Now, what I’ve got here are keys without any API restrictions within my Google Cloud Console. That’s fine for right now while we’re just developing our application. But we’ll want to make sure that we’re adding the appropriate restrictions to our API keys before our application is in production, in the hands of real users.

In theory, anybody who gets access to my API key can use Google’s services on my behalf. Google will think any requests — like displaying a map or searching for a location — come from my Google Cloud account and will be billed to me.

That obviously isn’t something you want, because it could mean a bad actor racking up a large bill.

So, we will want to add a proper restriction to these keys eventually. For now, while we’re developing, it’s perfectly fine to use an unrestricted key as long as we don’t share it.

Now, we actually have the choice of not using a Google Map element if our users are on iOS. There’s an option here to “Use Apple Maps on iOS.” If you tick that, we don’t need a Google Maps API key for iOS — the map will be provided by Apple Maps instead.

They function largely the same, but I’ll toggle this off so we use the Google Maps version and can all see how it works regardless of device.

There are other settings here to modify the map’s appearance — like the zoom level. You can even disable the ability for users to drag the map, meaning it stays fixed. I’m going to toggle that back on because we want that functionality.

The most important part, though, is this section up here — what markers we want to display on the map.

We could choose just a single marker. For example, I could search for a particular diary entry created by the current user that has a location field not empty, and grab the first item from that list. Then we need to provide a geographic address type of data, which we’ve saved in the location field for our diary entry.

If I load this up, you’ll see one marker appearing — seemingly in the center of London — and that corresponds to this diary entry here.

While testing, you can add other locations manually to your diary entries to view different spots on the map. Just note that unless you’ve set up your Geocode API key, you’ll only be able to add a certain number of addresses in a limited time.

That’s because if you leave this blank, you’re using Bubble’s own shared API key with Google. They only let you make a certain number of requests to format an address per time period.

What I mean by “format” is when I type something incomplete, see how it automatically formats correctly? That’s what Google is doing for us — turning it into a valid geographic address that can then be displayed on a map.

Now, showing a single marker isn’t that useful. So, instead, we can show a list of markers.

We’d choose where those markers come from — in our case, a list of diary entries. In the data source, we pick which diary entries to display. Our current search constraint is fine; we’re just showing the first item’s location, so let’s remove that.

Now we’re left with a search for diary entries, and we just need to tell the map which field holds the geographic address — that’s the location field.

If you test this out, you may see the map end up in the middle of the ocean. Because the mobile editor is still in beta, this element has a few rough edges. What helps is setting the center and zoom manually — center the map on one of the entries from your data source.

If we sort the entries by date (most recent first), we can grab the first one and set the center to its location. Set the initial zoom to something like 4 so all markers appear properly.

You can also customize the appearance of map markers. To learn how, click the “See reference” link when you hover over the dropdown — that’ll take you to the Bubble Manual. We’ll just keep the default markers.

Now, the last thing to do is allow a user to click on a marker and open the corresponding diary entry.

We can do that using a specific workflow action that becomes available once we have a map element on the page — “Maps marker is clicked.”

In that workflow, we’ll open the diary entry details view. Go to a view, open it in a stack, and set the target to the diary entry details. Then pass the diary entry from the selected map marker.

So: This map’s current marker → that’s the marker that was just tapped. The result evaluates to a diary entry.

In this way, we can click a diary entry marker and see it appear. Then, if we go back, we’re back on the map page. Brilliant.

Now, a small UX tweak: when a user opens a diary entry from the map, we might want to show the parent trip — because right now we’re viewing entries out of context. It makes sense that from a diary entry, we should be able to go to its trip.

To set this up, on the diary entry details view, add a text element at the top to display the trip title for the associated diary entry. We can get the diary entry from the view property we set up earlier, pull out its trip, and then the trip’s title value to display here.

Just so we can see something in the canvas, I might say something like this.

Let’s modify the styling so it looks clickable — bump up the font weight for boldness, and add an underline. The problem is, that underline looks too close to the text, so I’ll do it differently: remove the minimum height so the text element fits snugly around the text, then add a bottom border to act as an underline.

Set the border color to match the text, and it looks a lot better.

The text element is only 23 pixels high though — ideally, we want more click area. So, I’ll right-click, wrap it in a container (a group), and call it Group Parent Trip. This group will be the clickable element.

Set its height to 44 pixels, fit width to content, and center the text vertically.

Then add a workflow on this parent container: when clicked, go to view → open in a stack → target view = Trip Details.

Pass the trip associated with this diary entry (via the view property).

Now, if I click on one of my map markers, I see this clickable trip name (e.g., Cardiff City Break), and I can go to the parent trip. From there, I can open diary entries, add them to the stack, and go back through all views to the map.

One thing to note — if you go from a diary entry to a trip, then from that trip into another diary entry, and back again, you’ll build up a long stack. That may be fine, but we can make it smarter.

If you enter a diary entry from the map, then click the trip link, it should go back to the trip, not add a new view.

We can control that using a view property. Let’s add a new property:
opened_from_map (yes/no, not optional).

From the map view, set it to “yes” (since we’re opening from the map). From the trip details view, set it to “no.”

Then, within the diary entry details view, add conditional logic to the clickable group: only open the trip details when opened_from_map is yes.

Otherwise, just go to the previous view.

This means that if I open a diary entry from the map, then go to its trip, it adds a new view. But if I open one from within a trip, it goes back instead.

And that brings us to the end of this section on accessing our device’s resources.

Hopefully you’ve now got some intuition for how this works, so as Bubble adds support for more native device resources, you can build features around them in your app.

In the next section, things get serious — we’re going to learn how to secure our users’ data, how to schedule workflows to happen in the future, and, most excitingly, how to connect our app to external services like OpenAI.

So, I’ll see you in the next section.

Did this answer your question?