Angularjs, передающий объект директиве
Angular новичок здесь. Я пытаюсь выяснить, что происходит неправильно, передавая объекты в директивы.
здесь моя директива:
app.directive('walkmap', function() {
return {
restrict: 'A',
transclude: true,
scope: { walks: '=walkmap' },
template: '<div id="map_canvas"></div>',
link: function(scope, element, attrs)
{
console.log(scope);
console.log(scope.walks);
}
};
});
и это шаблон, где я называю директиву:
<div walkmap="store.walks"></div>
store.walks
- массив объектов.
Когда я запустил это, scope.walks
записывается как undefined
, а scope
записывает в качестве области видимости в полном объеме и даже имеет дочерний элемент walks
со всеми данными, которые я ищу.
Я не уверен, что я делаю неправильно здесь, потому что этот точный метод работал раньше для меня.
EDIT:
Я создал плункер со всем необходимым кодом: http://plnkr.co/edit/uJCxrG
Как вы видите, доступен в области видимости, но мне нужно получить доступ к ней в функции link, где она все еще регистрируется как undefined.
Ответы
Ответ 1
Так как вы используете $resource
для получения ваших данных, функция ссылки указывается до того, как данные будут доступны (поскольку результаты из $resource
являются асинхронными), поэтому первый раз в функции link scope.walks
будет be empty/undefined. Поскольку ваш шаблон директивы содержит {{}}
s, Angular устанавливает $watch
на walks
, поэтому, когда $resource
заполняет данные, триггеры $watch
и дисплей обновляются. Это также объясняет, почему вы видите данные ходьбы в консоли - к тому времени, когда вы нажмете ссылку, чтобы развернуть область, данные заселяются.
Чтобы решить вашу проблему, в вашей функции связи $watch
узнать, когда доступны данные:
scope.$watch('walks', function(walks) {
console.log(scope.walks, walks);
})
В вашем производственном коде просто предохраняйте его от undefined:
scope.$watch('walks', function(walks) {
if(walks) { ... }
})
Обновление: Если вы используете версию Angular, где $resource
поддерживает promises, см. также ответ @sawe.
Ответ 2
вы также можете использовать
scope.walks.$promise.then(function(walks) {
if(walks) {
console.log(walks);
}
});
Ответ 3
Другим решением было бы добавить ControllerAs
в директиву, с помощью которой вы можете получить доступ к переменным директивы.
app.directive('walkmap', function() {
return {
restrict: 'A',
transclude: true,
controllerAs: 'dir',
scope: { walks: '=walkmap' },
template: '<div id="map_canvas"></div>',
link: function(scope, element, attrs)
{
console.log(scope);
console.log(scope.walks);
}
};
});
И затем, на ваш взгляд, передайте переменную с помощью переменной ControllerAs
.
<div walkmap="store.walks" ng-init="dir.store.walks"></div>
Ответ 4
Попробуйте:
<div walk-map="{{store.walks}}"></div>
angular.module('app').directive('walkMap', function($parse) {
return {
link: function(scope, el, attrs) {
console.log($parse(attrs.walkMap)(scope));
}
}
});
Ответ 5
ваш объявленный объект $scope.store не отображается с контроллера. Вы объявляете его внутри функции. Так он видим только в области этой функции, вам нужно объявить это снаружи:
app.controller('MainCtrl', function($scope, $resource, ClientData) {
$scope.store=[]; // <- declared in the "javascript" controller scope
ClientData.get({}, function(clientData) {
self.original = clientData;
$scope.clientData = new ClientData(self.original);
var storeToGet = "150-001 KT";
angular.forEach(clientData.stores, function(store){
if(store.name == storeToGet ) {
$scope.store = store; //declared here it only visible inside the forEach
}
});
});
});