0
votes

I am newbie to Mapbox API and I am trying to develop something in which geojson files are returned from the server and the features are plotted on the map.

I am successful in plotting features on the map. What I do is look through all records and see if the geojson column has a value and if it does I fetch it from the server, make a new layer and plot it on that layer.

These are all polygons. What I need to do is to fire an event when I click on one of the polygons which is why I am using individual layers. Here is the code:

<script type="text/javascript">
        L.mapbox.accessToken = 'someKey';
        var map = L.mapbox.map('map', 'someMap')
            .setView([-39.67, -69.26], 4);

        $(document).ready(function(){
            $('header h2').text('Equipment Map');

            $.getJSON('distributor-companies', function (data) {
                var layers = [];
                $.each(data, function(i, item) {
                    if(item.geojson != ''){
                        var file = item.geojson;
                        layers[i] = L.mapbox.featureLayer().addTo(map);
                        $.getJSON('/geojson/' + file, function(data){
                            console.log('layer' + i);
                            layers[i].setGeoJSON(data);
                        });
                    }
                });
                $.each(layers, function(i, item){
                    console.log(item);
                    // item.on('click', function(e){
                    //  alert('hello');
                    // });
                });

                layers[32].on('click', function(e){
                    alert('hello');
                });
                layers[31].on('click', function(e){
                    alert('hello hi');
                });
            });
        });
    </script>

Now I take all the data from the distributor-companies route and make a new layer each time and plot data for every record. So at the end I am left with a lot of polygons.

In the end I am trying to individually register a click event listener on the layers which is working perfectly. But the code just before that where I am trying to loop through the layer is not working. The console.log function is showing me all the layers as object but when I try to register an on click event on the item it doesn't work and my console says TypeError item is undefined but console.log is working fine with it.

Clearly I am not a JavaScript expert and don't realize what am I doing wrong. I just need to loop through all the layers and place an onclick event on them.

1

1 Answers

5
votes

You don't need to add each feature as a separate featureGroup, it does that for you. Just instanciate the featureGroup with a GeoJSON featurecollection object:

var featureLayer = L.mapbox.featureLayer(geojson).addTo(map);

Then loop over added features, which are in fact just layers and add the onclick event to them:

featureLayer.eachLayer(function (layer) {
    layer.on('click', function (e) {
        // here e.target holds the layer
        // and e.target.feature holds the actual feature
        alert('Clicked layer ID: ' + e.target.feature.id);
     });
});

It's a simple as that. Working example on Plunker: http://plnkr.co/edit/31nQWnEnDYzNSmroZB8G?p=preview

If you want to keep it like you've got you can just do the above in your code like this:

$(document).ready(function(){
    $('header h2').text('Equipment Map');
    $.getJSON('distributor-companies', function (data) {
        var layers = [];
        $.each(data, function (i, item) {
            if (item.geojson != '') {
                layers[i] = L.mapbox.featureLayer().addTo(map);
                $.getJSON('/geojson/' + item.geojson, function (data) {
                    layers[i].setGeoJSON(data);
                    // Loop over the added layer
                    layers[i].eachLayer(function (layer) {
                        // Add click event
                        layer.on('click', function (e) {
                            // Do stuff
                            alert('Clicked layer ID: ' + e.target._leaflet_id);
                        });
                    });
                });
            }
        });
    });
});

If you want to work with just one featureLayer you could do something like this:

// Add empty featureLayer
var featureLayer = L.mapbox.featureLayer().addTo(map);

// Get URL index
$.getJSON('index.json', function (index) {
  // Create empty feature array
  var features = [];
  // Loop over URLs
  $.each(index, function (i, url) {
    // Fetch GeoJSON from URL
    $.getJSON(url, function (geojson) {
      // Push GeoJSON to array
      features.push(geojson);
      // Check if is last URL
      if (i == index.length - 1) {
        // Call addFeature with array
        addFeatures(features);
      }
    });
  });
});

function addFeatures (features) {
  // Set features in featureLayer
  featureLayer.setGeoJSON(features);
  // Loop over layers in featureLayer
  featureLayer.eachLayer(function (layer) {
    // Attach click handler
    layer.on('click', function (e) {
      // Do stuff
      alert('Clicked layer ID: ' + e.target.feature.id);
    });
  });
}

Here's a working on Plunker: http://plnkr.co/edit/dIMn9oiSpfsltq4iiilq?p=preview