Leaflet: Document layerGroup id option

Created on 28 Jun 2013  路  18Comments  路  Source: Leaflet/Leaflet

L.layerGroup has a function getLayer that finds layers by ids, but how layers _get_ ids is unexplained

L.layerGroup({ foo: L.tileLayer('') }).getLayer('foo') // no dice

Is there an id option for layers? This needs better explaining around.

docs

Most helpful comment

Leaflet 1.0 came out but there is still no way to access layers other than with getLayerId(layer) and getLayer(id)...

All 18 comments

1.Store result of getLayerId with a layer as an input
2.Use said resulting ID later to get layer

Isn't that the boiled down flow for using that function?

So like a full flow would be

var layer = L.tileLayer('foo');
var id = layer.getLayerId();
var group = L.layerGroup([layer]);
group.getLayer(id);

Seems a little kludgy?

Almost like this:

var layer = L.tileLayer('foo');
var group = L.layerGroup([layer]);
var id = group.getLayerId(layer);
...
group.getLayer(id);

Unless I'm missing something..isn't that it?

@tmcw what would a perfect API for this look like, any examples?

Hm - if ids are meant to be unique map-wide, then I guess this is the best way to do it. Otherwise I'm more or less looking for 'layer names' - a quick way to reference layers within a group with a certain identity. For instance,

L.layerGroup([markerLayer, tileLayer])

If you wanted to sweep through a map made up of multiple layergroups each with a markerlayer and tilelayer, it would be convenient to do something like

L.layerGroup({ marker: markerLayer, tile: tileLayer })

And access each as .layer('marker') or the like, rather than having to store ids as a separate var.

You can always get unique map-wide ids using L.stamp(layer). But this suggestion actually looks quite nice! Although we need to think through all API places which would be affected by this... E.g. now you need to also implement something like group.addLayer(layer, idInsideGroup) and layer.addTo(group, idInsideGroup). And should this somehow affect the use case of using feature.properties.id as your group id in GeoJSON?

Hey,

Just wanted to mention that LayerGroup.getLayerId isn't in the documentation at: http://leafletjs.com/reference.html#layergroup

Without that I would've had to resolve to accessing the _leaflet_id directly - something I didn't want to do.

This looks like a snake biting it's own tail,I am trying to use this with the L.geoJson in order to allow removing of features if nessecary,it looks like one needs a layer in order to get the layerId and one needs a layerId to get the layer. The only way I can think of for my situation has to be:

  1. Use a loop to convert each feature to geojson to check for my unique id from the database and get the index of that
  2. Use the getLayers method and obtain the _leaflet_id of the feature using the index.
  3. Remove the layer from the L.geoJson layer group.

Instead,one could save me so much iteration and return the _leaflet_id from addData in L.geoJson and addLayer in LayerGroup. I would then use the _leaflet_id to retrieve or remove the feature directly.

Is there a getter implemented ? I'm trying to acces to my _leaflet_id in onEachFeature function but it returns undefined...

Closing; focus is on 1.0

Leaflet 1.0 came out but there is still no way to access layers other than with getLayerId(layer) and getLayer(id)...

@tmcw Could you reopen this issue?

Hi @Lacroute, @mn113 and @zakjan,

Please can you kindly provide more context on your issue?

From what @vamsiampolu described, I understand that there is a "hole" when using L.geoJSON factory and/or its addData method, in that you provide GeoJSON data in, get a Layer Group full of Leaflet layers out, but you lose the one-to-one association between them in the process.
Therefore you have to loop through all items in the Layer Group to scan their _leaflet_id and match it with whatever id you have in your GeoJSON data / properties.

In the case of addData, this may be especially frustrating, as you may provide just a single new feature, but you do not directly get the newly created Leaflet layer. Therefore you have to scan through _all_ items in the group to find the new layer.

On the other hand, as for the addLayer method of Layer Group, I do not see the issue as you have to provide a Leaflet layer in the first place, on which you can get the _leaflet_id using L.stamp.

If this is your situation, then it seems to me that you could simply build a specific method, similar to addData, assuming that you provide a single feature (because adding an array of features / feature collection would make things much more complicated):

L.GeoJSON.include({
    addSingleFeature: function (geojson) {
        // Same as addData, without the management of array / feature collection.
        var options = this.options;

        if (options.filter && !options.filter(geojson)) { return this; }

        var layer = L.GeoJSON.geometryToLayer(geojson, options);
        if (!layer) {
            return this;
        }
        layer.feature = L.GeoJSON.asFeature(geojson);

        layer.defaultOptions = layer.options;
        this.resetStyle(layer);

        if (options.onEachFeature) {
            options.onEachFeature(geojson, layer);
        }

        this.addLayer(layer);

        // Return the newly created layer instead of this.
        return layer;
    }
});

Then you have to call it on individual GeoJSON feature, but you directly get the Leaflet layer that has been created.
Note also that you can no longer chain calls, since you get the new individual layer, not the parent Layer Group.

@ghybs
Thank you for your detailled answer. L.stamp seems to fix the problem, I'll try it soon.

To be more specific on my probelm, I was working on a GeoJSON dataset, and I used [onEachFeature](http://leafletjs.com/reference-1.0.0.html#geojson-oneachfeature) to loop through my features and bind some behaviors and store data. Then, when I wanted to update styles on the fly I was stuck beacause I couldn't use [getLayer](http://leafletjs.com/reference-1.0.0.html#layergroup-getlayer). the _leaflet_id was unaccessible... So after the onEachFeature loop, the only solution available was to loop again my LayerGroup returned from the L.GeoJSON method to store the id for later.

If you want to take a look, this was the project I worked on but be gentle, I did this piece of code in one weekend !

would the simplest solution to this, not be to set and get a custom id?

currently, my only option seems to be to add markers individually (storing them in an es6 map) and then modify them via the custom id that I use to store them there, which doesn't allow me to add them and manipulate them as a layer or feature group as far as I can tell.

@Pushplaybang not sure I fully understand the problem you're seeing, so feel free to expand with an example of what you mean by "doesn't allow me to add them and manipulate them as a layer or feature group"? Storing layers in a hash or ES6 map should work well.

As mentioned above, you can always get unique identifiers for an object using L.stamp(obj), if you don't want to generate identifiers yourself.

Note that there is a fair amount of interest in something like this, you can see that in these two so questions that have garnered a decent number of votes:

Disclosure: I do have answers on both of those but in neither are the "leaflet recommended" approach. Would be happy to update my answers if there is one or for someone else to submit a new answer if there is a better/simpler built-in approach.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

jblarsen picture jblarsen  路  3Comments

ssured picture ssured  路  3Comments

arminghm picture arminghm  路  3Comments

JonnyBGod picture JonnyBGod  路  4Comments

piehei picture piehei  路  3Comments