Mapbox Checkbox Filters – Combining Multiple Checkbox Filters in Mapbox

filtermapboxmapbox-gl-js

I am creating a Mapbox map in which I want multiple checkboxes to create an 'and' filter on one layer.

Here's the checkbox parts of my code so far:

<input type="checkbox" id="srBox" name="srBox" value="SustainableRecreation">
<label for="srBox"> Sustainable Recreation</label><br>

<input type="checkbox" id="hlBox" name="hlBox" value="HealthyLandscapes">
<label for="hlBox"> Healthy Landscapes</label><br>

<input type="checkbox" id="ovBox" name="ovBox" value="Overnight">
<label for="ovBox"> Overnight</label><br>



var checkbox = document.getElementById('srBox');
checkbox.addEventListener('change', function() {
  if (this.checked) {
    map.setFilter('rfovProjects', ['==', ['get', 'SR'], 'Y']);
  } else {
    map.setFilter('rfovProjects', null);
  }
});

var checkbox = document.getElementById('hlBox');
checkbox.addEventListener('change', function() {
  if (this.checked) {
    map.setFilter('rfovProjects', ['==', ['get', 'HL'], 'Y']);
  } else {
    map.setFilter('rfovProjects', null);
  }
});

var checkbox = document.getElementById('ovBox');
checkbox.addEventListener('change', function() {
  if (this.checked) {
    map.setFilter('rfovProjects', ['==', ['get', 'OV'], 'Y']);
  } else {
    map.setFilter('rfovProjects', null);
  }
});

If you look at the full map example (https://codepen.io/flyinginsect2/pen/oNoQvNQ), you'll see that if you click Healthy Landscapes and then Overnight, there are a few projects that show up. However, there are no projects that are in both of these categories.

How can I combine these filters?

I have a few more that I need to add in as well.

Best Answer

To achieve combined effect of selected filters you have to create a combined filter each time one of the individual filters change.

One way to do this is to have some filters object where you set key with individual filter name to true or false, depending on it's checked state.

Then on each individual filter change you iterate over filters keys and create and set Mapbox map filter accordingly. Relevant part of the code could then look something like this:

var filters = {};

function updateFilters() {
  var compositeFilter = ['all'];
  for (let filterValue in filters) {
    if (filters[filterValue]) {
      compositeFilter.push(['==', ['get', filterValue], 'Y']);
    }
  }
  if (compositeFilter.length > 1)
    map.setFilter('rfovProjects', compositeFilter);
  else {
    map.setFilter('rfovProjects', null);
  }
}

var checkbox = document.getElementById('srBox');
checkbox.addEventListener('change', function() {
  filters['SR'] = this.checked;
  updateFilters();
});

var checkbox = document.getElementById('hlBox');
checkbox.addEventListener('change', function() {
  filters['HL'] = this.checked;
  updateFilters();
});

var checkbox = document.getElementById('ovBox');
checkbox.addEventListener('change', function() {
  filters['OV'] = this.checked;
  updateFilters();
});

If you want to have OR filter, just substitute composite filter 'all' condition with 'any'.

Related Question