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

Angular - Следите за изменениями ngShow/ngHide в предках, которые влияют на детскую видимость элементов DOM

Я элемент DOM (привязанный, скажем, к таблице). Я являюсь дочерним элементом элемента управления вкладками ngShow. Я живу на второй вкладке. Когда страница визуализируется, я существую, но я пока не видим.

Я хотел бы как-то быть уведомленным, когда я становлюсь видимым через моего не-непосредственного родителя, когда его выражение ngShow станет истинным.

Возможно ли это? Я хотел бы избежать добавления кода вне себя - например, я бы предпочел не добавлять код в событие с измененной вкладкой. Я бы предпочел, чтобы зарегистрироваться, чтобы узнать, когда с помощью изменений в самых внешних контейнерах, которые связаны через ngShow/ngHide, моя видимость меняется. Это можно сделать?

4b9b3361

Ответ 1

Поскольку у вас есть область действия, доступная в директиве, вы можете использовать ее для просмотра изменений видимости:

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

EDIT 2014-02-24
Повторяя этот ответ на несколько месяцев, я заметил, что это работает, но немного замедлит ваш цикл дайджеста. Лучшая практика заключается в том, чтобы не использовать дорогие функции, например, для грязной проверки. Используйте с осторожностью!

Ответ 2

Лучший способ найти:

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

Удачи!

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

Я сделал это с директивой:

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.

Ответ 5

Другим возможным способом может быть использование $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
    }
})