[GIS] Popup with geojson data loaded using `Leaflet.FileLayer`

geojsonleaflet

I'm trying to create an interactive map using the Leaflet.FileLayer plugin. This plugin allows me to load geojson files with description but I don't know how to show this description in Popup when data is loaded from separate file. Normally, I call data using this code:

var miejsca_pamieci_l = L.geoJson(miejsca_pamieci, {
    pointToLayer: function (feature, latLng) {
      return new L.Marker(latLng, {
        icon: new myIcon({
          iconUrl: 'icon/cemetery-24.png',
          iconSize: [24, 24],
          iconAnchor: [12, 24],
          popupAnchor: [0, -24]
        })
      })
  },
onEachFeature: function( feature, layer ){
    layer.bindPopup (feature.properties.Opis, {  maxWidth: "auto"})
    }  });

But how to change the code to show popup using FileLayer? This is my script in html code:

  (function (window) {
    'use strict';
    function initMap() {
        var L = window.L;
        var osm = L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
            attribution: 'Map data © 2013 OpenStreetMap contributors'
        });
        var map = L.map('map', {
            center: [0, 0],
            zoom: 2
        }).addLayer(osm);
        var style = {
            color: 'red',
            opacity: 1.0,
            fillOpacity: 1.0,
            weight: 2,
            clickable: false
        };
        L.Control.FileLayerLoad.LABEL = '';
        L.Control.fileLayerLoad({
            fitBounds: true,
            layerOptions: {
                style: style,
                pointToLayer: function (data, latlng) {
                    return L.circleMarker(
                    latlng,
                    { style: style }
                    );
                }
            }
        }).addTo(map);
    }
    window.addEventListener('load', function () {
        initMap();
    });
}(window));

Best Answer

To make your popups with this plugin you have to do the following:

  1. Make sure your loaded geojson has "popupContent" in the feature properties, e.g.

    {
    "type": "FeatureCollection",
    "features": [
    {
      "type": "Feature",
      "properties": {
         "popupContent": "I'M GONNA POP UP!"
    },
    "geometry": {
      "type": "Polygon",
      "coordinates": [
    ....
    

    Of course you can also load values from other properties, but then remember to change the call to it in onEachFeature function.

  2. Set your layer style to clickable: true.

    var style = {
    ...
    clickable: true};
    
  3. Modify a little bit your L.Control.fileLayerLoad to make it a layer variable and add there onEachFeature function.

    var layer = L.Control.fileLayerLoad({
            fitBounds: true,
            layerOptions: {
                style: style,
                onEachFeature: onEachFeature,
                .....
    
  4. Finally add the onEachFeature function:

        function onEachFeature(feature, layer) {
            if (feature.properties && feature.properties.popupContent) {
                layer.bindPopup(feature.properties.popupContent);
            }
        }
    

Below you have the whole working example. LeafletJS scripts are loaded from CDNs, leaflet.filelayer.js is loaded from local, so while testing make sure you change it to your path.


<!DOCTYPE html>
<html lang="en">
<head>
    <title>Leaflet Filelayer </title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/4.2.0/normalize.min.css">
    <link rel="stylesheet" href="https://unpkg.com/leaflet@0.7.7/dist/leaflet.css">
    <style>
      .icon {
        max-width: 70%;
        max-height: 70%;
        margin: 4px;
      }
    </style>
</head>
<body>
    <div id="map" style="width: 100vw; height: 100vh;"></div>
</body>
<script src="https://unpkg.com/leaflet@0.7.7/dist/leaflet.js"></script>
<script src="https://unpkg.com/togeojson@0.14.2"></script>
<script src="leaflet.filelayer.js"></script>
<script>
  (function (window) {
    'use strict';
    function initMap() {
        var L = window.L;
        var osm = L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
            attribution: 'Map data &copy; 2013 OpenStreetMap contributors'
        });
        var map = L.map('map', {
            center: [0, 0],
            zoom: 2
        }).addLayer(osm);

        var style = {
            color: 'red',
            opacity: 1.0,
            fillOpacity: 1.0,
            weight: 2,
            clickable: true
        };

        L.Control.FileLayerLoad.LABEL = '<img class="icon" src="folder.svg" alt="file icon"/>';

        var layer = L.Control.fileLayerLoad({
            fitBounds: true,
            layerOptions: {
                style: style,
                onEachFeature: onEachFeature,
                pointToLayer: function (data, latlng) {
                    return L.circleMarker(
                    latlng,
                    { style: style }
                    );
                }
            }
        }).addTo(map);

        function onEachFeature(feature, layer) {
            // does this feature have a property named popupContent?
            if (feature.properties && feature.properties.popupContent) {
                layer.bindPopup(feature.properties.popupContent);
            }
        }

    }
    window.addEventListener('load', function () {
        initMap();
    });
}(window));
</script>
</html>

You can also check out this codepen to play around: http://codepen.io/dagmara223/pen/EZdZvp


pozdrowienia :)