1

I've created a GeoJSON with 3 points. This GeoJSON has fields called id and class inside its properties like the following:

{
    "type": "FeatureCollection",
    "features": [
        {
            "type": "Feature",
            "geometry": {
                "type": "Point",
                "coordinates": [-105.00341892242432, 39.75383843460583]
            },
            "properties": {
                "popupContent": "I'm in the first class",
                "underConstruction": false,
                "id": 1,
                "class": "layer1"
            }
        },
        {
            "type": "Feature",
            "geometry": {
                "type": "Point",
                "coordinates": [-105.0008225440979, 39.751891803969535]
            },
            "properties": {
                "popupContent": "I'm also in the first class",
                "underConstruction": false,
                "id": 2,
                "class": "layer1"
            }
        },
        {
            "type": "Feature",
            "geometry": {
                "type": "Point",
                "coordinates":  [-104.99820470809937, 39.74979664004068]
            },
            "properties": {
                "popupContent": "I'm in the second class",
                "underConstruction": false,
                "id": 3,
                "class": "layer2"
            }
        }
    ]
}

I'd like to find a way to make this id and class become a real id and class of the HTML elements they'll represent, just so I can use functions like document.getElementById, document.getElementByClassName, document.querySelectorAll or jquery to find points, polygons or polylines on my map. Something like the following:

const layer = L.geoJSON(geoJSON).addTo(map);

const iconElement = document.getElementsByClassName("layer1")
for (let i = 0; i < iconElement.length; i++) {
    iconElement[i].style.display = "none"
}

I have a JSfiddle of this code here... The problem is that the id and class that I've put inside the GeoJSON properties are not being recognized as the ids and classes of my markers. Is there any way of making Leaflet add these ids and classes properties to the features that are being created on the page? Just so I can find them with simple javascript DOM functions?

5
  • In the GeoJSON specification datatracker.ietf.org/doc/html/rfc7946 "If a Feature has a commonly used identifier, that identifier SHOULD be included as a member of the Feature object with the name "id", and the value of this member is either a JSON string or number." Maybe Leaflet could find it that way.
    – user30184
    Sep 29 at 8:09
  • This is possible, but to set marker icon HTML element ID would be rather complicated. Why would you need that? Whatever the reason is, it could probably be done some other simpler way.
    – TomazicM
    Sep 29 at 9:46
  • @user30184 I've actually tried putting it in different places on my GeoJSON but I think Leaflet is not doing it by default... Probably there's a manual way of doing it somehow
    – raylight
    Sep 30 at 1:00
  • @TomazicM Actually, I'm more interested in adding a class than adding the id... In my context, I'm always bringing small datasets of a Spatialite database to the frontend, and I'm converting the queries results to GeoJSON with ogr2ogr... If there was a simple way of adding classes on Leaflet, that would mean that I could group my data on the database and then manage it with DOM on the frontend (even though there are alternative ways of accomplishing the same using only Leaflet)
    – raylight
    Sep 30 at 1:04
  • 1
    (1) this is a XY problem (2) Leaflet may destroy and re-create DOM nodes unexpectedly causing race conditions (3) RTFM re: CSS classes on marker icons, put that together with the pointToLayer option (after reading the geojson tutorial). Sep 30 at 4:03
2

As @IvanSanchez mentioned in his comment, it's not a good practice to directly modify data structures that are managed by Leaflet, since Leaflet can change them any time.

The first problem of how to access individual features by their ID from GeoJSON can be solved by using internal Leaflet feature ids. Each feature in GeoJSON layer gets internal id, which can be retrieved by .getLayerId(featureLayer) method. Feature can then be directly accessed by GeoJSON layer .getLayer(featureLayerId) method. So what's needed is to create reference array, where elements, indexed by GeoJSON IDs, point to corresponding features.

Code for this could look something like this:

  var featureToLayer = [];
  
  var vectorLayer = L.geoJSON(data).addTo(map);
  
  vectorLayer.eachLayer(function (layer) {
    var layerId = vectorLayer.getLayerId(layer);
    featureToLayer[layer.feature.properties.id] = layerId;
  });
  
// To get feature where GeoJSON ID has value of 2:
  var feature = vectorLayer.getLayer(featureToLayer[2]);

What can now be done with this feature? If it's a point feature, displayed with some icon, icon can be changed with the .setIcon method. For example, to hide the icon, it can be set to custom L.divIcon that's hidden:

.noDisplay {
  display: none;
}

var hiddenIcon = L.divIcon({html: '', className: 'noDisplay'});
feature.setIcon(hiddenIcon);

// Set icon back to default
feature.setIcon(new L.Icon.Default);

If feature is vector layer, it's style can be changed to some custom style with the setStyle method:

feature.setStyle({color: '#ff0000'});

// Revert feature style to original
feature.setStyle();

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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