noodl-docs
noodl-docs copied to clipboard
Module(Mapbox): Custom Geocoder component
Improve documentation
Link
https://docs.noodl.net/2.9/library/modules/mapbox/guides/geocoder/
Describe the improvement
We should create a page descripting how to create a custom Geocoder / Address search component.
Additional context
Here is an example: https://mapbox-module-test.sandbox.noodl.app/geocoding-api
Search:
// Define the expected inputs for the script
Script.Inputs = {
Query: "string",
};
// Define the expected outputs for the script
Script.Outputs = {
Items: "array",
Searched: "signal",
};
// Set the endpoint URL for the Mapbox geocoding API
const ENDPOINT = 'https://api.mapbox.com/geocoding/v5/mapbox.places';
// Define an asynchronous function to make the API request
async function makeRequest() {
// Get the Mapbox access token from Noodl project settings
const access_token = Noodl.getProjectSettings().mapboxAccessToken;
// Encode the search query to be URL-safe
const search_text = encodeURIComponent(Script.Inputs.Query);
// Define query parameters for the API request
//
// Playground by Mapbox to test out all the features:
// https://docs.mapbox.com/playground/geocoding
//
// Here is a list of all the different possible types:
// - address
// - country
// - region
// - postcode
// - district
// - place
// - neighborhood
// - locality
// - poi
const queryParams = {
access_token, // Provide the access token
proximity: [Script.Inputs.lng, Script.Inputs.lat].join(','), // Bias results towards user's location
limit: 5, // Maximum number of results to return
// types: ["address"].join(","), // Filter results to include only addresses
// fuzzyMatch: true // Enable approximate matching
language: 'en-GB'
};
// Construct the query string from the query parameters
const query = Object.keys(queryParams)
.filter((key) => !!queryParams[key]) // Filter out empty values
.map((key) => `${encodeURIComponent(key)}=${encodeURIComponent(queryParams[key])}`)
.join('&');
// Make the API request and get the response as JSON
const response = await fetch(`${ENDPOINT}/${search_text}.json?${query}`);
const json = await response.json();
// Map the API response to an array of search results
const items = json.features.map((x) => Noodl.Object.create({
text: x.text,
place_name: x.place_name,
// Convert the array of [latitude, longitude] to a Geopoint
center: { latitude: x.center[0], longitude: x.center[1] }
}));
Script.Outputs.Items = items;
Script.Outputs.Searched();
}
Script.Signals = {
Search() {
makeRequest();
},
};
Center to the clicked item:
const items = Inputs.Items;
const itemId = Inputs.ItemId;
const item = items.find((x) => x.id === itemId);
if (!item) throw new Error("Cannot find clicked item.");
// The center geopoint of the clicked item.
const geopoint = item.center;
const mapboxObject = Inputs.MapboxObject;
if (!mapboxObject) throw new Error("Mapbox Object is invalid.");
mapboxObject.flyTo({
center: [geopoint.latitude, geopoint.longitude],
essential: true,
zoom: 15
});
The repeater item is just a button that is outputting a Click signal.