Create a Search Experience

Now you have simple app showing a map. In this step, you'll create a simple search and display the search results in a list. You'll also learn how to filter the data displayed on the map based on the search results.

MapsIndoors Locations can be retrieved in the mapsindoors namespace using the LocationsService.getLocations() method but first you need to add a <input> and <button> element to the DOM.

  • Create an <input> and <button> element in <body>.
  • Attach an onclick event to the <button> element and call a onSearch method, which you will create next.
<!-- index.html -->

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>MapsIndoors</title>
<script src="https://app.mapsindoors.com/mapsindoors/js/sdk/4.5.1/mapsindoors-4.5.1.js.gz?apikey=YOUR_MAPSINDOORS_API_KEY"></script>
<script src="https://maps.googleapis.com/maps/api/js?libraries=geometry&key=YOUR_GOOGLE_MAPS_API_KEY"></script>
</head>
<body>
<div id="map" style="width: 600px; height: 600px;"></div>
<script src="main.js"></script>
+ <input type="text" placeholder="Search">
+ <button onclick="onSearch()">Search</button>
</body>
</html>
  • Create the onSearch method.
  • Get a reference to the search <input> element.
  • Define a new object with the search parameter q and the value of searchInputElement.
  • Call the getLocations method and log out the results to the console.
// main.js

const mapViewOptions = {
element: document.getElementById('map'),
center: { lat: 38.8974905, lng: -77.0362723 }, // The White House
zoom: 17,
maxZoom: 22,
};
const mapViewInstance = new mapsindoors.mapView.GoogleMapsView(mapViewOptions);
const mapsIndoorsInstance = new mapsindoors.MapsIndoors({ mapView: mapViewInstance });
const googleMapsInstance = mapViewInstance.getMap();

// Floor Selector
const floorSelectorElement = document.createElement('div');
new mapsindoors.FloorSelector(floorSelectorElement, mapsIndoorsInstance);
googleMapsInstance.controls[google.maps.ControlPosition.RIGHT_TOP].push(floorSelectorElement);

+ function onSearch() {
+ const searchInputElement = document.querySelector('input');

+ const searchParameters = { q: searchInputElement.value };
+ mapsindoors.services.LocationsService.getLocations(searchParameters).then(locations => {
+ console.log(locations);
+ });
+ }

See all available search parameters in the reference documentation.

Using the <mi-search> component you get a <input>element tied tightly together with the Location Service.

  • Insert the <mi-search> custom element into <body>.
  • Add the mapsindoors and placeholder attributes.
<!-- index.html -->

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>MapsIndoors</title>
<script src="https://unpkg.com/@mapsindoors/components@8.2.0/dist/mi-components/mi-components.js"></script>
</head>
<body>
<mi-map-googlemaps style="width: 600px; height: 600px;" gm-api-key="YOUR_GOOGLE_MAPS_API_KEY" mi-api-key="YOUR_MAPSINDOORS_API_KEY" floor-selector-control-position="TOP_RIGHT">
</mi-map-googlemaps>
<script src="main.js"></script>
+ <mi-search
+ style="width: 600px;"
+ mapsindoors="true"
+ placeholder="Search">

+ </mi-search>
</body>
</html>
  • Get a reference to the <mi-search> element.
  • Attach an results event listener and log out the results to the console.
// main.js

const miMapElement = document.querySelector('mi-map-googlemaps');
+ const miSearchElement = document.querySelector('mi-search');

miMapElement.addEventListener('mapsIndoorsReady', () => {
miMapElement.getMapInstance().then((mapInstance) => {
mapInstance.setCenter({ lat: 38.8974905, lng: -77.0362723 }); // The White House
});
})

+ miSearchElement.addEventListener('results', (event) => {
+ console.log(event.detail);
+ });

For more information on available events and how to configure the <mi-search> component, see components.mapsindoors.com/search.

Show a List of Search Results

To display a list of search results you can append each search result to a list element.

  • Add the <ul> list element below the search field in <body> with the id attribute set to "search-results".
<!-- index.html -->

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>MapsIndoors</title>
<script src="https://app.mapsindoors.com/mapsindoors/js/sdk/4.5.1/mapsindoors-4.5.1.js.gz?apikey=YOUR_MAPSINDOORS_API_KEY"></script>
<script src="https://maps.googleapis.com/maps/api/js?libraries=geometry&key=YOUR_GOOGLE_MAPS_API_KEY"></script>
</head>
<body>
<div id="map" style="width: 600px; height: 600px;"></div>
<script src="main.js"></script>
<input type="text" placeholder="Search">
<button onclick="onSearch()">Search</button>
+ <ul id="search-results"></ul>
</body>
</html>
  • Insert the <mi-list> custom element below the search field in <body>.
  • Add the scroll-buttons-enabled and scroll-length attributes.
<!-- index.html -->

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>MapsIndoors</title>
<script src="https://unpkg.com/@mapsindoors/components@8.2.0/dist/mi-components/mi-components.js"></script>
</head>
<body>
<mi-map-googlemaps style="width: 600px; height: 600px;" gm-api-key="YOUR_GOOGLE_MAPS_API_KEY" mi-api-key="YOUR_MAPSINDOORS_API_KEY" floor-selector-control-position="TOP_RIGHT">
</mi-map-googlemaps>
<script src="main.js"></script>
<mi-search style="width: 600px;" mapsindoors="true" placeholder="Search">
</mi-search>
+ <mi-list
+ style="width: 600px; height: 400px;"
+ scroll-buttons-enabled="true"
+ scroll-length="200">

+ </mi-list>
</body>
</html>

For more information on how to configure the <mi-list> component, see components.mapsindoors.com/list.

  • Get a reference to the list element.
  • Reset the list on every complete search.
// main.js

const mapViewOptions = {
element: document.getElementById('map'),
center: { lat: 38.8974905, lng: -77.0362723 }, // The White House
zoom: 17,
maxZoom: 22,
};
const mapViewInstance = new mapsindoors.mapView.GoogleMapsView(mapViewOptions);
const mapsIndoorsInstance = new mapsindoors.MapsIndoors({ mapView: mapViewInstance });
const googleMapsInstance = mapViewInstance.getMap();

// Floor Selector
const floorSelectorElement = document.createElement('div');
new mapsindoors.FloorSelector(floorSelectorElement, mapsIndoorsInstance);
googleMapsInstance.controls[google.maps.ControlPosition.RIGHT_TOP].push(floorSelectorElement);

function onSearch() {
const searchInputElement = document.querySelector('input');
+ // Get list element reference
+ const searchResultsElement = document.getElementById('search-results');

const searchParameters = { q: searchInputElement.value };
+ mapsindoors.services.LocationsService.getLocations(searchParameters).then(locations => {
+ // Reset search results list
+ searchResultsElement.innerHTML = null;
+ });
}
// main.js

const miMapElement = document.querySelector('mi-map-googlemaps');
const miSearchElement = document.querySelector('mi-search');
+ const miListElement = document.querySelector('mi-list');

miMapElement.addEventListener('mapsIndoorsReady', () => {
miMapElement.getMapInstance().then((mapInstance) => {
mapInstance.setCenter({ lat: 38.8974905, lng: -77.0362723 }); // The White House
});
})

+ miSearchElement.addEventListener('results', (event) => {
+ // Reset search results list
+ miListElement.innerHTML = null;
+ });
  • Add a for loop and append every result to the search results list element.
// main.js

const mapViewOptions = {
element: document.getElementById('map'),
center: { lat: 38.8974905, lng: -77.0362723 }, // The White House
zoom: 17,
maxZoom: 22,
};
const mapViewInstance = new mapsindoors.mapView.GoogleMapsView(mapViewOptions);
const mapsIndoorsInstance = new mapsindoors.MapsIndoors({ mapView: mapViewInstance });
const googleMapsInstance = mapViewInstance.getMap();

// Floor Selector
const floorSelectorElement = document.createElement('div');
new mapsindoors.FloorSelector(floorSelectorElement, mapsIndoorsInstance);
googleMapsInstance.controls[google.maps.ControlPosition.RIGHT_TOP].push(floorSelectorElement);

function onSearch() {
const searchInputElement = document.querySelector('input');
// Get list element reference
const searchResultsElement = document.getElementById('search-results');

const searchParameters = { q: searchInputElement.value };
mapsindoors.services.LocationsService.getLocations(searchParameters).then(locations => {
// Reset search results list
searchResultsElement.innerHTML = null;

+ // Append new search results
+ locations.forEach(location => {
+ const listElement = document.createElement('li');
+ listElement.innerHTML = location.properties.name;
+ searchResultsElement.appendChild(listElement);
+ });
});
}
// main.js

const miMapElement = document.querySelector('mi-map-googlemaps');
const miSearchElement = document.querySelector('mi-search');
const miListElement = document.querySelector('mi-list');

miMapElement.addEventListener('mapsIndoorsReady', () => {
miMapElement.getMapInstance().then((mapInstance) => {
mapInstance.setCenter({ lat: 38.8974905, lng: -77.0362723 }); // The White House
});
})

miSearchElement.addEventListener('results', (event) => {
// Reset search results list
miListElement.innerHTML = null;

+ // Append new search results
+ event.detail.forEach(location => {
+ const miListItemElement = document.createElement('mi-list-item-location');
+ miListItemElement.location = location;
+ miListElement.appendChild(miListItemElement);
+ });
});

Filter Locations on Map Based on Search Results

To filter the map to only display the search results you can use the filter method.

  • Call mapsIndoorsInstance.filter with an array of location IDs.
// main.js

const mapViewOptions = {
element: document.getElementById('map'),
center: { lat: 38.8974905, lng: -77.0362723 }, // The White House
zoom: 17,
maxZoom: 22,
};
const mapViewInstance = new mapsindoors.mapView.GoogleMapsView(mapViewOptions);
const mapsIndoorsInstance = new mapsindoors.MapsIndoors({ mapView: mapViewInstance });
const googleMapsInstance = mapViewInstance.getMap();

// Floor Selector
const floorSelectorElement = document.createElement('div');
new mapsindoors.FloorSelector(floorSelectorElement, mapsIndoorsInstance);
googleMapsInstance.controls[google.maps.ControlPosition.RIGHT_TOP].push(floorSelectorElement);

function onSearch() {
const searchInputElement = document.querySelector('input');
// Get list element reference
const searchResultsElement = document.getElementById('search-results');

const searchParameters = { q: searchInputElement.value };
mapsindoors.services.LocationsService.getLocations(searchParameters).then(locations => {
// Reset search results list
searchResultsElement.innerHTML = null;

// Append new search results
locations.forEach(location => {
const listElement = document.createElement('li');
listElement.innerHTML = location.properties.name;
searchResultsElement.appendChild(listElement);
});

+ // Filter map to only display search results
+ mapsIndoorsInstance.filter(locations.map(location => location.id), false);
+ });
}
// main.js

const miMapElement = document.querySelector('mi-map-googlemaps');
const miSearchElement = document.querySelector('mi-search');
const miListElement = document.querySelector('mi-list');

miMapElement.addEventListener('mapsIndoorsReady', () => {
miMapElement.getMapInstance().then((mapInstance) => {
mapInstance.setCenter({ lat: 38.8974905, lng: -77.0362723 }); // The White House
});
})

miSearchElement.addEventListener('results', (event) => {
// Reset search results list
miListElement.innerHTML = null;

// Append new search results
event.detail.forEach(location => {
const miListItemElement = document.createElement('mi-list-item-location');
miListItemElement.location = location;
miListElement.appendChild(miListItemElement);
});

+ // Get the MapsIndoors instance
+ miMapElement.getMapsIndoorsInstance().then((mapsIndoorsInstance) => {
+ // Filter map to only display search results
+ mapsIndoorsInstance.filter(event.detail.map(location => location.id), false);
+ });

To remove the location filter again, call mapsIndoorsInstance.filter(null).

If you have followed the tutorial exactly so far, you will now have something like this:

Next up: Directions