How can you search your own CARTO dataset in a CARTO.js map?
Overview
In this example from the CARTO Developer Center we created a map with a dropdown menu. The dropdown menu lists the country names taken from the ne_adm0_europe
CARTO dataset’s admin
field.
When you select a country name from the dropdown menu, the map’s zoom level and center change to fit the bounding box of the selected country.
In order to achieve this effect we follow these steps:
- We create a CARTO.js map with one layer, as demonstrated in this example.
- Then, we create a
populateDrowpDown()
function. It uses a CARTO SQL API request to get the geometry and names of all countries in the CARTO dataset. Then, it populates the dropdown menu (defined with the HTML<select>
tag) with the names. This function is executed before the CARTO layer is added on the map. - Finally, we make another request to the CARTO SQL API to retrieve all data from the selected country, using the selected country’s HTML
value
attribute from the dropdown menu. Once we have that data, we can use Leaflet or Google Maps methods to fit the map’s bounds to the bounding box of the selected country.
CARTO SQL API request
We used the JavaScript Fetch API to make CARTO SQL API requests from our CARTO.js code. However, depending on your browser version the Fetch API might not be supported.
You can check if the Fetch API is supported for your browser here.
If your browser doesn’t support the Fetch API, you can use external libraries like Axios or JQuery to make the HTTP request to CARTO.
In this section of the CARTO Developer Center you can find detailed information about how make a CARTO SQL API call.
Differences between Leaflet and Google Maps approach
Because Leaflet and Google Maps have different methods, we have to make a different approach in order to get the same result.
In both cases, we retrieve the data from the CARTO SQL API to get the response as a GeoJSON.
Leaflet
In our example, we used Leaflet fitBounds and getBounds methods.
First we used getBounds() to find the layer’s bottom-left and top-right bounding box. Then, we used fitBounds() to change the map’s zoom and center so it fit the bounding box.
document.getElementById('selectDrop').addEventListener("change", function (e) {
input = e.currentTarget.selectedOptions[0].attributes[0].value;
return fetch(`https://cartojs-test.carto.com/api/v2/sql?format=geojson&q=SELECT * FROM ne_adm0_europe where admin Ilike '${input}'`)
.then((resp) => resp.json())
.then((response) => {
geojsonLayer = L.geoJson(response)
map.fitBounds(geojsonLayer.getBounds());
})
});
Google Maps
In Google Maps we used a CARTO SQL API request to retrieve the maximum and minimum longitude and latitude values of the selected country’s bounding box, as shown in this SQL query:
WITH bbox as (
SELECT ST_Envelope(the_geom) as the_geom
FROM ne_adm0_europe
WHERE admin Ilike '${input}'
)
SELECT the_geom, ST_Xmax(the_geom) as xmax,
ST_Ymax(the_geom) as ymax,
ST_Xmin(the_geom) as xmin,
ST_Ymin(the_geom) as ymin
FROM bbox
First we calculated the selected country’s bounding box using the PostGIS ST_Envelope method. Once we had the bounding box, we found its maximum and minimum longitude and latitude values using the ST_X and ST_Y PostGIS methods.
We used the maximum and minimum longitude and latitude values with google.maps.LatLng and google.maps.LatLngBounds to get geographical coordinates for the rectangle containing the country polygon.
// set LatLng objects from coordinates from CARTO
let sw = new google.maps.LatLng(coordinates.ymin, coordinates.xmin);
let ne = new google.maps.LatLng(coordinates.ymax, coordinates.xmax);
// instantiate Google bounds
bounds = new google.maps.LatLngBounds(sw, ne)
For the last step we used that bounds object with the Google Maps fitBounds method, to fit the map to the selected country’s bounding box by changing its zoom level and center.
// set bounds of map to the geometry from CARTO
map.fitBounds(bounds);
Here you can see the complete block of code:
document.getElementById('selectDrop').addEventListener("change", function (e) {
input = e.currentTarget.selectedOptions[0].attributes[0].value;
// calculate the xmax, ymax, xmin, ymin coordinates of the bounding box
// of the country polygon of the CARTO dataset
return fetch(
`https://cartojs-test.carto.com/api/v2/sql?format=geojson&q=
WITH bbox as (
SELECT ST_Envelope(the_geom) as the_geom
FROM ne_adm0_europe
WHERE admin Ilike '${input}'
)
SELECT the_geom, ST_Xmax(the_geom) as xmax,
ST_Ymax(the_geom) as ymax,
ST_Xmin(the_geom) as xmin,
ST_Ymin(the_geom) as ymin
FROM bbox
`)
.then((resp) => resp.json())
.then((response) => {
// get coordinates
coordinates = response['features'][0].properties
// set LatLng objects from coordinates from CARTO
let sw = new google.maps.LatLng(coordinates.ymin, coordinates.xmin);
let ne = new google.maps.LatLng(coordinates.ymax, coordinates.xmax);
// instantiate Google bounds
bounds = new google.maps.LatLngBounds(sw, ne)
// set bounds of map to the geometry from CARTO
map.fitBounds(bounds);
})