8

I have a GeoJSON point layer group styled as a circle marker; it has a color attribute which can be one of many values: white, black, blue, red etc.

I want to create a filter based on that attribute, so I created a Bootstrap button with a Dropdown for a selection of four attributes.

I tried the built-in filter as pointed in this question,

var redcolor = L.geoJson(colors, {filter: redFilter})

function redFilter(feature) {
  if (feature.properties.hue === "red") return true
}

and assigning it to its respective button using jQuery:

$("#red").click(function(event) {
    event.preventDefault();
    if(map.hasLayer(redcolor)) {
        $(this).removeClass('selected');
        map.removeLayer(redcolor);
    } else {
        map.addLayer(redcolor);        
        $(this).addClass('selected');
   }
})

but I don't want to create a separate layer group; the filtering should happen in the original one.

4
  • I'm unclear on what you mean by "I don't want to create a separate layer" and "the original one". Is 'redcolor' the "original layer"? Your variable 'redcolor' is a layer which contains only the features for which the function redFilter returns true.
    – cmrRose
    Commented May 16, 2018 at 15:41
  • @cmrRose By "original" I mean the layer contaning all the unfiltered points from the GeoJSON (which is in another variable). You are right about 'redcolor' and it works fine, but it doesn't actually filter the 'red' points; it creates another layer and I end up with duplicates. I want the filter button to work with a single layer.
    – Cezar B
    Commented May 16, 2018 at 16:14
  • I didn't quite understand when I commented earlier, but your redcolor --or any result of L.geoJson-- is a Leaflet "LayerGroup". stackoverflow.com/questions/10425553/… while each individual point is a "layer"
    – cmrRose
    Commented May 16, 2018 at 20:58
  • Thank you for the note; I knew the difference, but being used to the term "layer" from GIS, I didn't realize the mistake. I edited the question and the problem remains.
    – Cezar B
    Commented May 17, 2018 at 5:29

2 Answers 2

9

You need to create a grouplayer and from that you can add or remove the layer, in that way refreshing the data with the filter from the same dataset.

Here are two working examples: the first using buttons, the second radio buttons.

http://bl.ocks.org/zross/47760925fcb1643b4225

http://www.gistechsolutions.com/leaflet/DEMO/filter/filter.html

4

Here is an example of using a dropdown to filter out values in the geojson layer.

JS Bin: https://jsbin.com/sasojat/edit?html,js,output

There are many possible solutions, but this one works like this:

  1. Create a variable to store the layergroup and a variable to contain the filter-out value.

    var dataLayerGroup;

    var filterval = document.getElementById("filter").value;

  2. Write your filter function to test for not-matching the filter-out variable.

    var colorFilter = function (feature) {
    if (feature.properties.color !== filterval) return true}
    
  3. Create a function that deletes the layer if it exists, then adds it again.

    function addLayerToMap(){
     //remove the layer from the map entirely
     if (map.hasLayer(dataLayerGroup)){
         dataLayerGroup.remove();
     }
     //add the data layer and style based on attribute. 
     dataLayerGroup = L.geoJson(pointsData, {
         filter: colorFilter,
         pointToLayer: function(feature, latlng) {
             return new L.CircleMarker(latlng, {radius: 8, fillOpacity: 0.85});
         },
         onEachFeature: function (feature, layer) {
             layer.bindPopup(feature.properties.color);
         }, 
         style: function(feature){
             return{color:  feature.properties.markercolor};
           },  
         }).addTo(map);
     }
    
  4. Create a listener for the filter input

     $("#filter").on("input", function(){
     filterval = document.getElementById("filter").value;
     console.log("the filter was changed to ", filterval); 
     //add the layer to the map again, now that we have changed the filter value. 
     addLayerToMap();
     });
    
  5. Call the function to add the layer to the map for the first time

     addLayerToMap();
    

I'm still slightly unclear on why you don't want to use separate layergroups for each filter option, like the links that Bill posted do, but maybe this alternative will help you.

1
  • After trying several things, including your example, I decided to go with several layergroups, even if I'm not entierly sure if it's the best option. Thank you for your help!
    – Cezar B
    Commented Jun 12, 2018 at 21:15

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.