Угловая директива не собирает служебные данные
Мой сервис NavData
angular.module('navData', []).
factory('NavData', function() {
var navData = {};
navData.depth = 0;
navData.category_id = "";
navData.category_name = "";
navData.subcategory_id = "";
navData.subcategory_name = "";
return navData;
});
получает значения от ui-router на несколько страниц:
var category = {
name: 'category',
parent: site,
url: '/categories/:category_id',
onEnter: function(NavData, $stateParams){
NavData.depth = 1;
NavData.category_id = $stateParams.category_id;
console.log(NavData);
},
views: {
'navigation': {
templateUrl: 'partials/category-menu.html'
},
'content': {
templateUrl: 'partials/category-images.html'
}
}
};
Директива, появляющаяся на всех страницах, должна следить за изменениями в сервисе и отражать их в специальной функции:
.directive('breadcrumb', ['NavData', function(NavData){
return {
templateUrl: 'partials/breadcrumb.html',
link: function(scope, elm, attrs, ctrl){
scope.depth = NavData.depth;
scope.category_id = NavData.category_id;
scope.category_name = NavData.category_name;
scope.subcategory_name = NavData.subcategory_name;
var doStuff = function(navdata){
console.log("watching depth: " + navdata.depth);
console.log("watching cat_id: "+ navdata.category_id);
};
scope.$watch(NavData.depth, doStuff(NavData), true);
scope.$watch(NavData.category_id, doStuff(NavData), true);
}
};
}])
Однако scope.$ Watch, похоже, не работает. Это мой журнал:
watching depth: 0 directives.js:28
watching cat_id: directives.js:29
watching depth: 0 directives.js:28
watching cat_id: directives.js:29
Object {depth: 1, category_id: "1", category_name: "", subcategory_id: "", subcategory_name: ""} app.js:25
Что я делаю неправильно?
2 ответа
Ваша первая ошибка в scope.$watch()
1-й аргумент: это либо выражение (строка), вычисленное в заданном scope
или функция, возвращающая значение; значение сохраняется, и функция запускается в каждом цикле дайджеста; если новое значение отличается, слушатель (2-й аргумент) срабатывает.
Итак, первое исправление:
scope.$watch(function() {
return NavData.depth,
}, .../*other arguments, see below*/);
Теперь и второй аргумент неверен! Ожидается, что это будет функция, вы предоставляете возвращаемое значение функции (которая, кстати, не определена для doStuff
). Эта функция 2-го аргумента получает новое значение (как возвращено 1-м аргументом выше), старое значение и область видимости. В вашем случае вас не волнует новое / старое значение. Таким образом, полное решение должно быть:
scope.$watch(function() { // decide the watched value
return NavData.depth,
}, function() { // what to do when the value changes
// do stuff and reference NavData normally
});
Если предположить, NavData
изменяется только ui-router
onEnter
обратные вызовы, вы могли бы пропустить весь NavData
объект и $watch
реализация.
Просто транслируйте событие на каждом onEnter
Перезвоните:
onEnter: function($rootScope, $stateParams){
$rootScope.$broadcast("NavDataChanged", {
depth: 1,
category_id: $stateParams.category_id
/* (any other former NavData properties) */
});
}
И ваша директива станет:
.directive('breadcrumb', [function(){
return {
templateUrl: 'partials/breadcrumb.html',
link: function(scope, elm, attrs, ctrl){
scope.$on("NavDataChanged", function(event, navData) {
scope.depth = navData.depth;
scope.category_id = navData.category_id;
// any other former NavData properties and doStuff code
});
}
};
}])
Упрощенная версия здесь.