0

I've been struggling to get map filters to work on my Leaflet map. I've got minimal JavaScript or Leaflet knowledge so where I have got to now has been a struggle. I'm essentially trying to do the following

https://jsfiddle.net/chrisjenner/jq1emofz/

I have tried to replicate this but without any joy. I'm sure it's fairly simple but with limited knowledge, I haven't been able to fix it. My version of the above can be found below where I am trying to filter a layer by a Boolean field. Carp and Tench are species and my sample dataset is for lakes. I want to be able to filter by these.

https://jsfiddle.net/chrisjenner/02crteao/64/

Below is my code

<div class="input" id="carp">
      <input type="checkbox" class="carp" name="1" value="1" checked="true">
      <label for="1">Carp</label>
    </div>

    <div class="input" id="tench">
      <input type="checkbox" class="tench" name="1" value="1" checked="true">
      <label for="1">Tench</label>
    </div>

    const lakes = L.geoJSON(lakes_data, {
  style: function(feature) {
    return {
      color: feature.properties.color
    };
  }
  },
  {filter: (feature) => {
    const isCarpChecked = checkboxStates.carp.includes(feature.properties.carp)
    const isTenchChecked = checkboxStates.tench.includes(feature.properties.tench)
    return isCarpChecked && isTenchChecked //only true if both are true
  }
}).bindPopup(function(layer) {
  return layer.feature.properties.name;
}).addTo(map);

function updateCheckboxStates() {
  checkboxStates = {
    carp: [],
    tench: []
  }

for (let input of document.querySelectorAll('input')) {
    if (input.checked) {
      switch (input.className) {
        case 'carp':
          checkboxStates.carp.push(input.value);
          break
        case 'tench':
          checkboxStates.tench.push(input.value);
          break
      }
    }
  }
}

for (let input of document.querySelectorAll('input')) {
   input.onchange = (e) => {
    lakes.clearLayers()
    updateCheckboxStates()
    lakes.addData(lakes_data)
  }
}

updateCheckboxStates()
lakes.addData(lakes_data)
2
  • 3
    Please Edit your Question to contain the relevant block(s) of code.
    – Vince
    Commented Jan 24, 2021 at 2:30
  • 1
    @Vince can you reopen my question, please. Commented Jan 25, 2021 at 8:29

1 Answer 1

1

In such cases the only solution is browser debugger, break points and inspection of variable contents. If you would do this and set break point inside filter function, you would see that isCarpChecked and isTenchChecked are never set to true, since checkbox value is string "1", but feature property is numeric 1.

Simple solution to this is to convert input.value string to numeric value in updateCheckboxStates function:

function updateCheckboxStates() {
  checkboxStates = {
    carp: [],
    tench: []
  }

  for (let input of document.querySelectorAll('input')) {
    if (input.checked) {
      var numValue = parseInt(input.value);
      switch (input.className) {
        case 'carp':
          checkboxStates.carp.push(numValue);
          break;
        case 'tench':
          checkboxStates.tench.push(numValue);
          break;
      }
    }
  }
}

Besides that your GeoJSON layer filter option is not specified correctly, too many curly brackets, and there is no need to specify GeoJSON source, since you'll be filling it later with the results of check boy status:

const lakes = L.geoJSON(null, {
  style: function(feature) {
    return {
      color: feature.properties.color
    };
  },
  filter: (feature) => {
    const isCarpChecked = checkboxStates.carp.includes(feature.properties.carp)
    const isTenchChecked = checkboxStates.tench.includes(feature.properties.tench)
    return isCarpChecked && isTenchChecked //only true if both are true
  }
}).bindPopup(function(layer) {
  return layer.feature.properties.name;
}).addTo(map);

Here is working JSFiddle: https://jsfiddle.net/TomazicM/L9ctqnbs/.

6
  • Hi @TomazicM - thank you for your reply. That makes perfect sense about the numeric value. I tried to replace my cod with yours above but still no joy. I also tired to change the feature properties to string as well which didn't work either. I appreciate this is more down to me than your solution! :) Commented Jan 25, 2021 at 10:58
  • Ups, I forgot one other error, see modified answer.
    – TomazicM
    Commented Jan 25, 2021 at 14:23
  • that's definitely a step in the right direction thank you but I have noticed it only works for the data that has both tench and carp = 1. I'd like to make this more dynamic if possible. Can it be set up so that the tick boxes start off empty and the filter happens on click? So if I ticked just carp all the lakes with carp were shown irrelevant of other checkboxes. Thank you again for your help. Commented Jan 26, 2021 at 19:17
  • Of course it can be, but this problem is pure JS logic problem and as such outside the scope of GIS SE site, which is intended for GIS related questions. It should be posted on StackOverflow site. And yes, I noticed that problem and suspected it will come up :-)
    – TomazicM
    Commented Jan 26, 2021 at 19:29
  • So you'd recommend closing this down and reopening? I'm not sure what the best practice is sorry. Commented Jan 26, 2021 at 19:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.