1

Goal: Show markers for lat-lon positions from a CSV file. The other columns need to be placed in pop-up as attributes.

CSV file can be seen at: airport.csv

Code:

headers = ['iata', 'title', 'city', 'state', 'country'] // determined programmatically and excludes latitude longitude

customLayerLocalData = L.geoJson(null, {
    onEachFeature: function (feature, layer) {
        var popupContent = '';
        $.each(headers, function (h) {
            popupContent += feature.properties + '.' + headers[h];
            if (h != headers.length - 1) {
                popupContent += '+'
            };

        });
        layer.bindPopup(popupContent);
    },
    pointToLayer: function (feature, latlng) {
        return L.circleMarker(latlng, customMarkerOptions);
    }
});
layerLocalData = omnivore.csv.parse(fr.result, null, customLayerLocalData).addTo(map);

Problem: The pop-up shows the object:

 [object Object].iata
+[object Object].title
+[object Object].city
+[object Object].state
+[object Object].country

If I change: layer.bindPopup(popup content); to layer.bindPopup(eval(popup content));, it works. But, I am not happy with this solution (does not feel right). Morever, in this case new lines can't be inserted inside the custom geoJSON layer.

I'm looking for a smarter solution that can interpret the 'popupContent' and pass onto to layer.bindPopup correctly.

Vince
  • 20,017
  • 15
  • 45
  • 64
PDash
  • 383
  • 2
  • 12

2 Answers2

1

This is a javascript problem regarding object property accessors.

So when you're doing this...

 popupContent += feature.properties + '.' + headers[h];

What you want is to access e.g. feature.properties.iata when headers[h] has the value "iata". And it's failing, because the code is doing string concatenation instead.

The approach here is to read and re-read how object property accessors work, and then

 popupContent += feature.properties[ headers[h] ];

As a bonus, you can get rid of the jQuery iterators and the manual concatenation of "+" by levaraging Array.prototype.map and Array.prototype.join, e.g.:

onEachFeature: function (feature, layer) {
    var popupContent = headers.map(function (header){
        return feature.properties[header];
    }).join('+');

    layer.bindPopup(popupContent);
},
IvanSanchez
  • 10,206
  • 2
  • 19
  • 35
  • This is an expert, to-the-point, answer and very much appreciated. I ended up with:

    var popupContent = headers.map(function (header) {return header + ':' + feature.properties[header];}).join('<br>');

    The other approach from my prev link below also worked, but I prefer this .map: l.bindPopup('<pre>' + JSON.stringify(f.properties, null, ' ').replace(/[\{\}"]/g, '') + '</pre>'. Unsure why someone gave it -1, but that was also okay.

    – PDash Feb 21 '20 at 16:18
-1

It was tricky a bit but someone savvy has answered it in a different context here:

Displaying properties of GeoJSON in popup on Leaflet?

I am not closing/deleting this QnA; someone else like me may need it. Thanks.

PDash
  • 383
  • 2
  • 12