Angular - 观察影响子DOM元素可见性的祖先中的ngShow / ngHide更改

时间:2013-05-22 23:33:48

标签: javascript angularjs

我是一个DOM元素(绑定到一个表)。我是基于ngShow的选项卡控件的下游子代。我住在第二个标签上。当页面被渲染时,我存在,但我还不是真的可见。

当我的非直系父母看到它的ngShow表达式变为真时,我想以某种方式得到通知。

这可能吗?我想避免在我自己以外的任何地方添加代码 - 例如,我宁愿不在某个地方更改选项卡中添加代码。我宁愿有办法注册,通过ngShow / ngHide绑定的最外层容器的变化来查明我的可见性变化。可以这样做吗?

5 个答案:

答案 0 :(得分:21)

由于指令中有可用的范围,您可以使用它来监视可见性的变化:

scope.$watch(function() { return element.is(':visible') }, function() {
  // Do whatever should happen when the visibility changes
});

这可以避免轮询可见性,这可能会影响性能。当然,这假定范围由任何导致可见性改变的因素应用。我已经在我自己的指令中尝试过,但与ngShow / ngHide无关。

信用到期的信用:这最初是由我提出的(不是我):
https://groups.google.com/d/msg/angular/w7Gxa5M_17M/koYCZnsobawJ

编辑2014-02-24
几个月后重新回答这个答案,我注意到这个有效,但会慢慢减慢你的消化周期。最佳做法是不要使用诸如此类的昂贵功能进行脏检查。请谨慎使用!

答案 1 :(得分:8)

我找到的最佳方式:

link: function (scope, element, attr) {
    attr.$observe('ngShow', function (expr) {
        scope.$watch(function () {
            return $parse(expr)(scope);
        }, function (value) {
            console.log(value)
        })
    });
}

祝你好运!

答案 2 :(得分:4)

我用指令做了这个:

Elemement:

<test-directive ng-show="showMe" show-model="showMe"></test-directive>

指令:

app.directive('testDirective', function() {
    return {
        restrict: 'E',
        scope: {
            showModel: "=?",
        },
        controller: function($scope) {
            if (angular.isDefined($scope.showModel)) {
                $scope.$watch('showModel', function(newValue, oldValue) {
                    // Do stuff
                });
            }
        }
     }
});

因此,我们的想法是将$ watch放在与ng-show链接的同一个变量上。

答案 3 :(得分:3)

我唯一能想到的就是创建一个循环指令来查看元素是否可见。类似的东西:

angular.module('testModule', [])
  .directive('onVisible', ['$timeout', function($timeout) {
    return {
      restrict: 'A',
      scope: {
        onVisible: '&'
      },
      link: function(scope, element, attrs) {
        var checkVisibility = function() {
              if (element.is(':visible')) {
                scope.onVisible();
              } else {
                $timeout(checkVisibility, 100);
              }
            };
        $timeout(checkVisibility, 100);
      }
    };
  }]);

当然,如果每次元素变得可见时都需要执行它,你还需要注意元素转换回隐藏。

编辑:这假设您有jQuery可用。

答案 4 :(得分:3)

另一种可能的方法是使用$ broadcast。选择标签后,您可以广播活动

$scope.$broadcast('secondTabSelected');

您可以在控制器内处理此事件并进行进一步处理。

$scope.$on('secondTabSelected', function(e){
    // do something awesome.
})

每次选项卡可见时,都会通知您。只执行一次,你可以做

var firstTimeSelected = false;
$scope.$on('secondTabSelected', function(e){
    if(firstTimeSelected){
        firstTimeSelected = true;
        // do something awesome
    }
})