Angularjs注意父范围的变化

时间:2013-07-24 15:40:31

标签: javascript angularjs scope

我正在编写指令,我需要观察更改的父作用域。我不确定我是否喜欢这样做,但它不能使用以下代码:

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

5 个答案:

答案 0 :(得分:73)

如果要查看父作用域的属性,可以使用父作用域中的$watch方法。

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

2016年编辑: 上面应该工作得很好,但它并不是一个干净的设计。尝试使用directivecomponent,并将其依赖项声明为绑定。这应该会带来更好的性能和更清洁的设计。

答案 1 :(得分:21)

我建议你使用控制器之间的$ 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();
      });
    }
  };
});

答案 2 :(得分:7)

您的子范围应该具有 data 属性,范围使用父范围和子范围之间的原型继承。

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

答案 3 :(得分:6)

如果您正在寻找在子范围内观看父范围变量,您可以在true上添加$watch作为第二个参数。这将在每次修改对象时触发您的手表

$scope.$watch("searchContext", function (ctx) {
                ...
            }, true);

答案 4 :(得分: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");
});

我在这里展示的是你可以拥有一个变量,它具有来自孩子和父母的双向绑定,但不要求孩子达到它的父亲来获得属性。如果你在指令上面添加一个新的父级,那么伸手去抓东西的倾向会变得疯狂。

如果在框中键入,它将更新控制器上的模型,而这又会绑定到指令上的属性,因此它将在指令中更新。在指令链接功能中,它具有监视设置,因此只要范围变量发生变化,它就会递增计数器。

详细了解隔离范围以及使用= @或&amp;的差异在这里:http://www.egghead.io/