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: '© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, © <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.