1

I'm trying to add/remove markers to a leaflet map. I have 6 checkboxes, what i want is that when I check any of them show the points in the map, and when uncheck one of them the only to remove is the one I uncheck.

What I have,

The checkboxes:

.row
    .col-md-12
        .row
            label.col-md-7 First check
            input.col-md-1(type="checkbox" ng-model="locations.somecheck1")
        .row
            label.col-md-7 Second check
            input.col-md-1(type="checkbox" ng-model="locations.somecheck2")
        .row
            label.col-md-7 Third check
            input.col-md-1(type="checkbox" ng-model="locations.somecheck3")
        .row
            label.col-md-7 Fourth check
            input.col-md-1(type="checkbox" ng-model="locations.somecheck4")
        .row
            label.col-md-7 Five check
            input.col-md-1(type="checkbox" ng-model="locations.somecheck5")
        .row
            label.col-md-7 Six check
            input.col-md-1(type="checkbox" ng-model="locations.somecheck6")

The controller:

$scope.$watch('locations.somecheck1', function(somecheck1) {

      if ($scope.locations.somecheck1 === true) {
        findItem.find(function(err, items) {

          lastLocationItems = items[0].items;
          items = lastLocationItems.map((item) => GeoService.toGeoJSON(item, { idKey: '_id', geometryKey: 'lastLocation'}));
          getEpc(items, ssccIcon);
        });
      } else {
        leafletData.getMap().then(function(map) {

          map.removeLayer(objetosLayer);
        });
      }
    }, true);

The function that create the layer:

function getEpc(items, icon) {
      var objectsLayer = L.geoJson(items, {
        pointToLayer: function(items, latlng) {
          var result;

          if (icon !== undefined) {
            result = L.marker(latlng, {
              icon: icon
            });
          } else {
            result = L.marker(latlng);
          }

          return result;
        }
      });

      leafletData.getMap().then(function(map) {

        objectsLayer.addTo(map);
      });
    }

In the watch function, is the remove function that activates when the checkbox is false. If I check 2 checkbox, the function create both, but when I want to remove the first one, only removes the second check. I look and found that every time I click a checkbox it's create a new layer with the new info.

How can I automatically create a layer for every checkbox in the function getEpc?

1

Save a reference to your object layer(s) and then remove them before re-adding to avoid duplicates. It looks like you were already on the right track, but your current objectsLayer has a scope inside getEpc().. you need to define this at a higher level, and you need to maintain a separate layer for each checkbox.

Note that Leaflet already supports this concept out-of-box by using the Layers control. You can create overlays, add them to the layers control, and use checkboxes to automatically toggle the layers, which will add and remove them for you.

However, if you want to do it on your own, you need to do a few things:

First, modify getEPC() to return a reference to the new layer:

function getEpc(items, icon) {
  var objectsLayer = L.geoJson(items, {
    pointToLayer: function(items, latlng) {
      var result;
      if (icon !== undefined) {
        result = L.marker(latlng, {
          icon: icon
        });
      } else {
        result = L.marker(latlng);
      }
      return result;
    }
  });
  leafletData.getMap().then(function(map) {
    objectsLayer.addTo(map);
  });
  // return layer reference so we can manage it
  return objectsLayer;
}

Then, you need to manage the layers as you add and remove them.

Note: it will get very tedious to do this for each checkbox.. you may want to use a watchGroup or watchCollection instead. But to keep the example simple, I tried to use your code without making major modifications:

// global cache for overlays. 
// you may want to put this somewhere better, but keeping example simple..
var overlays = {};

$scope.$watch('locations.somecheck1', function(somecheck1) {
  if ($scope.locations.somecheck1 === true) {
    findItem.find(function(err, items) {
      lastLocationItems = items[0].items;
      items = lastLocationItems.map((item) => GeoService.toGeoJSON(item, { idKey: '_id', geometryKey: 'lastLocation'}));
      var objectsLayer = getEpc(items, ssccIcon); // get new layer
      // save layer reference so it can be removed later
      overlays["somecheck1"] = objectsLayer; 
    });
  } else if(overlays["somecheck1"]) {
    leafletData.getMap().then(function(map) {
      map.removeLayer(overlays["somecheck1"]); // remove cached layer
    });
  }
}, true);

$scope.$watch('locations.somecheck2', function(somecheck1) {
  if ($scope.locations.somecheck2 === true) {
    findItem.find(function(err, items) {
      lastLocationItems = items[0].items;
      items = lastLocationItems.map((item) => GeoService.toGeoJSON(item, { idKey: '_id', geometryKey: 'lastLocation'}));
      var objectsLayer = getEpc(items, ssccIcon); // get new layer
      // save layer reference so it can be removed later
      overlays["somecheck2"] = objectsLayer; 
    });
  } else if(overlays["somecheck2"]) {
    leafletData.getMap().then(function(map) {
      map.removeLayer(overlays["somecheck2"]);
    });
  }
}, true);

// etc, for each checkbox (but prefer to refactor into smaller, reusable methods)

  • Thanks for the reply @nothingisnecessary, i have done what you suggest, but there's a way to add different layers with the getEpc function to show differents markers at the same time? And what typo for objetosLayer do you mean? Thanks again. – diego Sep 12 '15 at 13:01
  • Yep, you can store the objectsLayers in an array, for example. hit ctrl-f and search for "objetosLayer" and you will see it – nothingisnecessary Sep 12 '15 at 19:26
  • Sorry, but where should I hit ctrl-f and search for objetosLayer? – diego Sep 13 '15 at 23:42
  • In this page. Controller code you posted is doing map.removeLayer(objetosLayer) – nothingisnecessary Sep 14 '15 at 1:36
  • After re-reading your question I figured I could post a more specific answer for dealing with multiple layers. See updated code above. However, you may be better off using the Layers control that leaflet already provides because it does this for you (toggling geoJson layers with a checkbox and a nice interface). See details here: leafletjs.com/examples/layers-control.html – nothingisnecessary Sep 14 '15 at 2:19

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.