[GIS] Filter geoJSON layer after it has been loaded

filtergeojsonlayersleaflet

I'm declaring and defining a geoJSON layer first, like:

var layer1 = L.geoJson(null, {
   onEachFeature: function(feature, layer) {
   ...
   }
});

..and then loading a CSV into it, like:

omnivore.csv('pbstatus.csv', null, layer1 )
   .on('ready', function(e) {
       ...
});

Now, I want to create other geoJSON layers as subsets of layer1 based on the value of one of the CSV's columns loaded into the layer's feature.properties dataset. Is there a way to filter layer1 AFTER it's been defined and loaded? I'm aware of the 'proper' way of filtering when defining the layer:

var layer1 = L.geoJson(null, {
   onEachFeature: function(feature, layer) {
   ...
   },
   filter: function(feature, layer) {
   return (feature.properties.foo == 'bar');
   }
});

.. but I don't want to repetitively do a different declaration each time. And, the data in the CSV is going to decide which layers and how many to form; we may not know all the possible filter conditions before we have imported the CSV. Is there a way I can spawn new layers as subsets of this layer1 after it's been loaded with geoJSON data ? Would the new layers also inherit the properties, actions and behaviours set in layer1's onEachFeature: function?

Best Answer

just came across this again and realised I hadn't updated that I found an answer.

I initiated empty layers beforehand:

var statusComplete = L.layerGroup().addTo(map);     layerControl.addOverlay(statusComplete, 'Complete');
var statusProgress = L.layerGroup().addTo(map);     layerControl.addOverlay(statusProgress, 'Work in Progress');
var statusUnfinished = L.layerGroup().addTo(map);   layerControl.addOverlay(statusUnfinished, 'Left Unfinished');
var statusNotstarted = L.layerGroup().addTo(map);   layerControl.addOverlay(statusNotstarted, 'Work not Started');
var statusUnsure = L.layerGroup().addTo(map);       layerControl.addOverlay(statusUnsure, 'Unsure');

Inside the onEachFeature function, I added layer.addTo() statements.

var statusLayer = L.geoJson(null, {
   onEachFeature: function(feature, layer) {
   ...
    var statusCheck = feature.properties['Actual Status'].toLowerCase();
    if( statusCheck == 'complete' ) layer.addTo(statusComplete);
    else if( statusCheck == 'work in progress' ) layer.addTo(statusProgress);
    else if( statusCheck == 'left unfinished' ) layer.addTo(statusUnfinished);
    else if( statusCheck == 'work not started' ) layer.addTo(statusNotstarted);
    else layer.addTo(statusUnsure);

}

The features added to the other layers carried on whatever I defined for them in this "mother" layer : marker icons, popups, tooltips. This was useful; I did not have to repeat the same lines of code again for five different layers.

And though the CSV itself was loaded (via omnivore) into the "mother" layer, I never actually added it to either the map or the layerControl. It stayed invisible, while the new layers statusComplete, statusProgress, statusUnfinished, statusNotstarted, statusUnsure were added to the map.

You may see the full code here.

PS: I'm not really sure why I initiated the child layers as L.layerGroup(), and not sure how else to initiate them.

Related Question