Подтвердить что ты не робот

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();
      });
    }
  };
});
4b9b3361

Ответ 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/