45

我正在写一个指令,我需要观察父范围的变化。不确定我是否以首选方式执行此操作,但它不适用于以下代码:

  scope.$watch(scope.$parent.data.overlaytype,function() {
    console.log("Change Detected...");
  })

它记录了窗口加载,但永远不会再登录,即使覆盖类型已更改。

我如何观察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();
      });
    }
  };
});
4

5 回答 5

76

如果要查看父范围的属性,可以使用$watch父范围的方法。

//intead of $scope.$watch(...)
$scope.$parent.$watch('property', function(value){/* ... */});

编辑 2016: 上面应该可以正常工作,但它并不是一个真正干净的设计。尝试使用指令组件,并将其依赖项声明为绑定。这应该会带来更好的性能和更简洁的设计。

于 2014-03-31T12:47:50.400 回答
23

我建议您在控制器之间使用 $broadcast 来执行此操作,这似乎更像是父/子控制器之间通信的角度方式

这个概念很简单,你在父控制器中观察值,然后,当发生修改时,你可以广播它并在子控制器中捕获它

这是一个演示它的小提琴: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();
      });
    }
  };
});
于 2013-07-24T16:02:20.527 回答
7

您应该在子作用域上拥有data属性,作用域在父作用域和子作用域之间使用原型继承。

此外,$watch方法期望的第一个参数是要计算的表达式或函数,而不是来自变量的值。所以你应该发送它。

于 2013-07-24T15:47:13.020 回答
7

如果您正在寻找在子范围内查看父范围变量,您可以true$watch. 每次修改对象时都会触发您的手表

$scope.$watch("searchContext", function (ctx) {
                ...
            }, true);
于 2015-08-26T08:44:15.817 回答
2

好吧,这花了我一段时间,这是我的两分钱,不过我也喜欢事件选项:

更新了小提琴 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/

于 2013-07-24T16:27:50.453 回答