Skip to content

Filter Features by Toggle List

Toggle category buttons to show or hide specific feature types on the map using setFilter().

Toggle categories:

Filter by Active Categories

Track which categories are selected, then build a filter expression:

javascript
const activeCategories = new Set(['restaurant', 'cafe', 'hotel']);

function applyFilter() {
  const active = [...activeCategories];

  if (active.length === 0) {
    // Hide everything
    map.setFilter('places-layer', ['==', '1', '0']);
  } else {
    // Show features whose category is in the active list
    map.setFilter('places-layer', [
      'in',
      ['get', 'category'],
      ['literal', active]
    ]);
  }
}

// Toggle a category on/off
function toggleCategory(category) {
  if (activeCategories.has(category)) {
    activeCategories.delete(category);
  } else {
    activeCategories.add(category);
  }
  applyFilter();
}

Filter Expressions

javascript
// Show only restaurants
map.setFilter('layer', ['==', ['get', 'category'], 'restaurant']);

// Show restaurants OR cafes
map.setFilter('layer', [
  'in',
  ['get', 'category'],
  ['literal', ['restaurant', 'cafe']]
]);

// Remove filter (show all)
map.setFilter('layer', null);

// Hide all
map.setFilter('layer', ['==', '1', '0']);

Complete Example

html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <link href="https://cdn.mapmetrics-atlas.net/versions/latest/mapmetrics-gl.css" rel="stylesheet" />
    <script src="https://cdn.mapmetrics-atlas.net/versions/latest/mapmetrics-gl.js"></script>
    <style>#map { height: 500px; width: 100%; }</style>
  </head>
  <body>
    <div id="map"></div>
    <div>
      <button class="cat-btn" data-cat="restaurant">Restaurant</button>
      <button class="cat-btn" data-cat="cafe">Cafe</button>
      <button class="cat-btn" data-cat="hotel">Hotel</button>
    </div>
    <script>
      const map = new mapmetricsgl.Map({
        container: 'map',
        style: '<StyleFile_URL_with_Token>',
        center: [2.3499, 48.853],
        zoom: 13
      });

      const active = new Set(['restaurant', 'cafe', 'hotel']);

      map.on('load', () => {
        map.addSource('places', {
          type: 'geojson',
          data: {
            type: 'FeatureCollection',
            features: [
              { type: 'Feature', properties: { category: 'restaurant' }, geometry: { type: 'Point', coordinates: [2.344, 48.856] } },
              { type: 'Feature', properties: { category: 'cafe' }, geometry: { type: 'Point', coordinates: [2.333, 48.854] } },
              { type: 'Feature', properties: { category: 'hotel' }, geometry: { type: 'Point', coordinates: [2.337, 48.860] } },
            ]
          }
        });

        map.addLayer({
          id: 'places-layer',
          type: 'circle',
          source: 'places',
          paint: { 'circle-radius': 9, 'circle-color': '#3b82f6', 'circle-stroke-width': 2, 'circle-stroke-color': '#fff' }
        });

        function applyFilter() {
          const list = [...active];
          map.setFilter('places-layer', list.length
            ? ['in', ['get', 'category'], ['literal', list]]
            : ['==', '1', '0']
          );
        }

        document.querySelectorAll('.cat-btn').forEach(btn => {
          btn.addEventListener('click', () => {
            const cat = btn.dataset.cat;
            active.has(cat) ? active.delete(cat) : active.add(cat);
            applyFilter();
          });
        });
      });
    </script>
  </body>
</html>
jsx
import React, { useEffect, useRef, useState } from 'react';
import mapmetricsgl from '@mapmetrics/mapmetrics-gl';
import '@mapmetrics/mapmetrics-gl/dist/mapmetrics-gl.css';

const categories = ['restaurant', 'cafe', 'hotel'];

const placesData = {
  type: 'FeatureCollection',
  features: [
    { type: 'Feature', properties: { category: 'restaurant' }, geometry: { type: 'Point', coordinates: [2.344, 48.856] } },
    { type: 'Feature', properties: { category: 'cafe' }, geometry: { type: 'Point', coordinates: [2.333, 48.854] } },
    { type: 'Feature', properties: { category: 'hotel' }, geometry: { type: 'Point', coordinates: [2.337, 48.860] } },
  ]
};

const FilterByToggleList = () => {
  const mapContainer = useRef(null);
  const map = useRef(null);
  const [active, setActive] = useState(new Set(categories));

  useEffect(() => {
    if (map.current) return;
    map.current = new mapmetricsgl.Map({
      container: mapContainer.current,
      style: '<StyleFile_URL_with_Token>',
      center: [2.3499, 48.853],
      zoom: 13
    });

    map.current.on('load', () => {
      map.current.addSource('places', { type: 'geojson', data: placesData });
      map.current.addLayer({
        id: 'places-layer', type: 'circle', source: 'places',
        paint: { 'circle-radius': 9, 'circle-color': '#3b82f6', 'circle-stroke-width': 2, 'circle-stroke-color': '#fff' }
      });
    });

    return () => { map.current?.remove(); map.current = null; };
  }, []);

  useEffect(() => {
    if (!map.current) return;
    const list = [...active];
    map.current.setFilter?.('places-layer', list.length
      ? ['in', ['get', 'category'], ['literal', list]]
      : ['==', '1', '0']
    );
  }, [active]);

  const toggle = (cat) => {
    setActive(prev => {
      const next = new Set(prev);
      next.has(cat) ? next.delete(cat) : next.add(cat);
      return next;
    });
  };

  return (
    <div>
      <div ref={mapContainer} style={{ height: '500px', width: '100%' }} />
      <div style={{ marginTop: '8px', display: 'flex', gap: '8px' }}>
        {categories.map(cat => (
          <button
            key={cat}
            onClick={() => toggle(cat)}
            style={{
              padding: '6px 12px',
              background: active.has(cat) ? '#3b82f6' : 'white',
              color: active.has(cat) ? 'white' : '#3b82f6',
              border: '2px solid #3b82f6',
              borderRadius: '20px',
              cursor: 'pointer'
            }}
          >
            {cat}
          </button>
        ))}
      </div>
    </div>
  );
};

export default FilterByToggleList;

For more information, visit the MapMetrics GitHub repository.