TransWikia.com

Use self-defined Leaflet identifiers to work with jsTree checkboxes

Geographic Information Systems Asked by McOS on November 12, 2021

I have some hierachic structured point-layers in a GeoJSON file using jsTree (ajax) with checkboxes to add them to the map. As I have about 20.000 points structured in 2.000 nodes representing the layers I have to to it in an automated way.

My idea is to connect the jsTree id with an id in the GeoJSON, so the Node ID of the jstree corresponds with the “treeid” (node.id===treeid, both are strings) in the GeoJSON file. The string ID’s are generated in a Database and exported as JSON. Each checkbox adds an ID assigned layer to a layergroup on the map. Unchecking should remove that particular layer. The user can activate as much checkboxes as he likes.

Based on this question I set the default _leaflet_id equal to the “treeid” to use it as an identifier for each Layer. This works basically.

Example of the GeoJSON:

var collection = {"type": "FeatureCollection","crs": {"type": "name","properties": {"name": "urn:ogc:def:crs:OGC:1.3:CRS84"}},   "features": [{ "type": "Feature",
   "properties": {
     "dta_1": "Node_1",
     "treeid": '01 01 002 00001'
   },
   "geometry": {
     "type": "Point",
     "coordinates": [38.933333, 40.816667]
   }
 },
 {
   "type": "Feature",
   "properties": {
     "dta_1": "Node_2",
     "treeid": '01 01 002 00002'
   },
   "geometry": {
     "type": "Point",
     "coordinates": [38.9551, 40.7626]
   }}]}

Example of the jsTree (simple JSON):

$('#data').jstree({'core': {'data': [{
     "id": "01",
     "parent": "#",
     "text": "Root"
   }, {
     "id": "01 01 002 00001",
     "parent": "01",
     "text": "Node_1"
   }, {
     "id": "01 01 002 00002",
     "parent": "01",
     "text": "Node_2"
   } ...

My checkbox code:

var group = {}; 
var layergroup =  L.layerGroup().addTo(map);
$('#data').on("check_node.jstree", function(e, data) {
            group =  L.geoJson(collection, {    
            onEachFeature: function(feature, layer) {
                           layer._leaflet_id = data.node.id;},      
            filter: function(feature, layer) {
                    if (feature.properties.treeid==data.node.id) return true}});
            group.treeid = data.node.id
            group.addTo(layergroup);
 /*         layergroup.eachLayer(function(layer){
            layer._leaflet_id = data.node.id;
            }) */
     })
.on("uncheck_node.jstree", function(e, data){
layergroup.eachLayer(function(e){
if (e._layers[data.node.id]) layergroup.removeLayer(e);})});
//   if (layer._leaflet_id === data.node.id) {
//   layergroup.removeLayer(layer)}

A working fiddle is here: jsfiddle

Using the “onEachFeature” Function works fine for one point, it is removed correctly. So I thought, it works, but as you can see in the fiddle, if there are many points (Node_2) again only one point (the first one) is added to the map. (Because only the first one is assigned?)

Using the “eachLayer” method adds all points as expected, but of course the uncheck code doesn’t work. Changing to the outcommented code does not work.

Where is the point I’m missing on the “onEachfeature” Function to add all points with the same treeid?

Or the other option: How to change the uncheck code?

I need to add all points with the same id referencing a specific node.id to a layergroup by a checkbox, unchecking it should remove them from the layergroup and the map.

One Answer

I don't quite understand the intended logic of jsfiddle code, but there is definitely no need to load GeoJSON on each tree node selection/click, it can be loaded once at the beginning and then it's features iterated through when neccessary.

The other thing is that you should never modify internal Leaflet _leaflet_id property. You can only read it with getLayerId method of group layer and later use it to get desired layer with getLayer method.

In the code below (only relevant part from jsfiddle) GeoJSON features are loaded only once into featureLayer group layer, which is not added to map. Then upon tree node selection/unselecton features in featureLayer are iterated through and layer with id property that corresponds to tree node id is added/removed to layergroup layer:

var featureLayer = L.geoJson(collection);

$('#data')
  .on("check_node.jstree", function(e, data) {
    featureLayer.eachLayer(function (layer) {
      if (layer.feature.properties.treeid == data.node.id) {
        layer.addTo(layergroup);
      };
    });
  })

  .on("uncheck_node.jstree", function(e, data) {
    layergroup.eachLayer(function(layer){
      if (layer.feature.properties.treeid == data.node.id) {
        layergroup.removeLayer(layer);
      };
    })
  });

Answered by TomazicM on November 12, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP