Angularjs наблюдают за изменением родительского охвата
Я пишу директиву, и мне нужно посмотреть родительскую область для изменения. Не уверен, что я делаю это предпочтительным способом, но не работает со следующим кодом:
scope.$watch(scope.$parent.data.overlaytype,function() {
console.log("Change Detected...");
})
Это он регистрируется при загрузке окна, но никогда больше, даже когда overlaytype изменен.
Как я могу смотреть overlaytype
для изменения?
Изменить: вот вся Директива. Не совсем уверен, почему я получаю детскую область.
/* Center overlays vertically directive */
aw.directive('center',function($window){
return {
restrict : "A",
link : function(scope,elem,attrs){
var resize = function() {
var winHeight = $window.innerHeight - 90,
overlayHeight = elem[0].offsetHeight,
diff = (winHeight - overlayHeight) / 2;
elem.css('top',diff+"px");
};
var watchForChange = function() {
return scope.$parent.data.overlaytype;
}
scope.$watch(watchForChange,function() {
$window.setTimeout(function() {
resize();
}, 1);
})
angular.element($window).bind('resize',function(e){
console.log(scope.$parent.data.overlaytype)
resize();
});
}
};
});
Ответы
Ответ 1
У вас должно быть свойство данных в области вашего дочернего объекта, области применения используют прототипное наследование между родительскими и дочерними областями.
Кроме того, первый аргумент, который ожидает метод $watch, является выражением или функцией для оценки, а не значения переменной. Поэтому вы должны отправить это вместо.
Ответ 2
Если вы хотите посмотреть свойство родительской области, вы можете использовать метод $watch
из родительской области.
//intead of $scope.$watch(...)
$scope.$parent.$watch('property', function(value){/* ... */});
EDIT 2016:
Вышеизложенное должно работать очень хорошо, но это не совсем чистый дизайн. Попробуйте использовать directive или component вместо этого и объявлять свои зависимости как привязки. Это должно привести к повышению производительности и более чистому дизайну.
Ответ 3
Я бы предложил вам использовать $broadcast между контроллером для выполнения этого, что, по-видимому, больше angular способ связи между родительскими/дочерними контроллерами
Концепция проста, вы смотрите значение в родительском контроллере, затем, когда происходит модификация, вы можете транслировать ее и перехватывать в дочернем контроллере
Вот скрипка, демонстрирующая это: http://jsfiddle.net/DotDotDot/f733J/
Часть в родительском контроллере выглядит следующим образом:
$scope.$watch('overlaytype', function(newVal, oldVal){
if(newVal!=oldVal)
$scope.$broadcast('overlaychange',{"val":newVal})
});
и в дочернем контроллере:
$scope.$on('overlaychange', function(event, args){
console.log("change detected")
//any other action can be perfomed here
});
Хорошая точка с этим решением, если вы хотите посмотреть изменения в другом дочернем контроллере, вы можете просто поймать одно и то же событие
Удачи
Изменить: я не видел последнее редактирование, но мое решение работает и для директивы, я обновил предыдущую скрипку (http://jsfiddle.net/DotDotDot/f733J/1/)
Я изменил вашу директиву, чтобы заставить ее создать дочернюю область и создать контроллер:
directive('center',function($window){
return {
restrict : "A",
scope:true,
controller:function($scope){
$scope.overlayChanged={"isChanged":"No","value":""};
$scope.$on('overlaychange', function(event, args){
console.log("change detected")
//whatever you need to do
});
},
link : function(scope,elem,attrs){
var resize = function() {
var winHeight = $window.innerHeight - 90,
overlayHeight = elem[0].offsetHeight,
diff = (winHeight - overlayHeight) / 2;
elem.css('top',diff+"px");
};
angular.element($window).bind('resize',function(e){
console.log(scope.$parent.data.overlaytype)
resize();
});
}
};
});
Ответ 4
Если вы ищете просмотр родительской переменной сферы внутри дочерней области, вы можете добавить true
в качестве второго аргумента на $watch
. Это вызовет ваши часы каждый раз, когда ваш объект будет изменен.
$scope.$watch("searchContext", function (ctx) {
...
}, true);
Ответ 5
Хорошо, что мне потребовалось некоторое время здесь, мои два цента, мне тоже нравится опция события:
Обновлена скрипка
http://jsfiddle.net/enU5S/1/
HTML
<div ng-app="myApp" ng-controller="MyCtrl">
<input type="text" model="model.someProperty"/>
<div awesome-sauce some-data="model.someProperty"></div>
</div>
JS
angular.module("myApp", []).directive('awesomeSauce',function($window){
return {
restrict : "A",
template: "<div>Ch-ch-ch-changes: {{count}} {{someData}}</div>",
scope: {someData:"="},
link : function(scope,elem,attrs){
scope.count=0;
scope.$watch("someData",function() {
scope.count++;
})
}
};
}).controller("MyCtrl", function($scope){
$scope.model = {someProperty: "something here");
});
То, что я показываю здесь, это то, что вы можете иметь переменную, которая имеет двустороннюю привязку от дочернего элемента и родителя, но не требует, чтобы ребенок достиг своего родителя, чтобы получить свойство. Тенденция к достижению чего-то может сходить с ума, если вы добавите нового родителя над директивой.
Если вы введете в поле, он обновит модель на контроллере, это, в свою очередь, привязано к свойству в директиве, чтобы оно обновлялось в директиве. Внутри функции ссылок директив у нее есть настройка часов, поэтому в любое время, когда переменная области изменяется, она увеличивает счетчик.
Подробнее об изоляционной области и различиях между использованием = @и здесь: http://www.egghead.io/