20

我是一个 DOM 元素(例如,绑定到一个表)。我是基于 ngShow 的选项卡控件的下游子级。我住在第二个标签上。呈现页面时,我存在,但我还没有真正可见。

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

这可能吗?我想避免在我自己之外的任何地方添加代码——例如,我不想在某个地方的 tab-changed 事件中添加代码。我宁愿有一种方法来注册,以通过 ngShow/ngHide 绑定的最外层容器的更改来了解我的可见性何时发生变化。这可以做到吗?

4

5 回答 5

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
几个月后重新审视这个答案,我注意到这很有效,但会大大减慢你的消化周期。最佳实践是不要使用诸如此类的昂贵函数进行脏检查。谨慎使用!

于 2013-07-17T11:22:35.757 回答
8

我发现的最好方法:

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

祝你好运!

于 2014-04-08T09:36:07.043 回答
4

我用指令做到了这一点:

元素:

<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 的同一个变量上。

于 2014-03-19T10:27:43.990 回答
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。

于 2013-05-22T23:47:52.667 回答
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
    }
})
于 2015-10-27T10:26:06.500 回答