Use scope as id to create map in Leaflet

In view i use ng-repeat which allow me to use $index for each item, i try to use this property to create one map for each item in ng-repeat

View

 <div map-directive id="map{{$index}}" name="'map' + [$index]" class="mapContainers">
 </div>

SO now id is map0, map1 and so on.

Directive

    var map = L.map(scope.name, {
                        center: [40.766964, -73.930453],
                        zoom: 4,
                        layers: [BaseMap]
                    });

In directive scope.name contain unique id.

I found out that map works only after changing scope on string

    var map = L.map('map', {
                        center: [40.766964, -73.930453],
                        zoom: 4,
                        layers: [BaseMap]
                    });

Maybe somebody have had similar problem already.

Why go out of your way to use ID's when you can simply use the directive's element attribute which is supplied by the link method? It's there for a reason, might just use it as well:

angular.module('app', [
  'ui.router'
]);

angular.module('app').config([
  '$stateProvider',
  '$urlRouterProvider',
  function ($stateProvider, $urlRouterProvider) {
    $urlRouterProvider.otherwise('/');
    $stateProvider.state('root', {
      'url': '/',
      'controller': ['$scope', function ($scope) {
          $scope.maps = ['a', 'b', 'c', 'd'];
      }],
      'template': '<div map-directive ng-repeat="map in maps" class="map"></div>'
    });
  }
]);

angular.module('app').directive('mapDirective', function () {
  return {
    restrict: 'A',
    link: function (scope, element, attrs) {
      var map = L.map(element[0], {
        center: [0, 0],
        zoom: 1,
        layers: [
          L.tileLayer('http://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png', {
            attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, &copy; <a href="http://cartodb.com/attributions">CartoDB</a>',
            maxZoom: 18
          })  
        ]
      });
    }
  };
});

Works like a charm: http://plnkr.co/edit/toZByf9QSletY5erXID7?p=preview

I'll try to explain what's actually happening here. If you add an ID by using a template string:

<div map-directive ng-repeat="map in maps" id="map_{{$index}}" class="map"></div>

The directives link (pre or post, doesn't matter) function get executed:

'link': function (scope, element, attrs) {
    console.log(element[0]);
    console.log(attr.id);
}

Here attrs.id returns map_0 for the first element in the ng-repeat, that's great. We've got an ID. But element[0] (the actual element that's been created) at this point still returns: div#map_{{$index}}.map. So if you tell L.Map to use map_0 as the element ID, the ID hasn't been parsed yet although the element is already present in the DOM thus L.Map throws you an error that it can't find the element: Map container not found.

The way to do it is by using the element attribute, it holds a reference of the actual element and L.Map accepts that too as you can see by it's signature:

L.map( <HTMLElement|String> id, <Map options> options? )

http://leafletjs.com/reference.html#map-l.map

If you assign a reference to the actual element (since you've got it, why not?) it saves L.Map from having to preform a DOM lookup for the ID, so that's even better. You can still assign the ID if you need it for CSS purposes or something, it's just of no use in the directive for this purpose.