AngularJS watch DOM change

前端 未结 5 2046
生来不讨喜
生来不讨喜 2020-11-29 05:31

I have one auto-carousel directive which iterates through the linked element\'s children.

The children however are not yet loaded in th

相关标签:
5条回答
  • 2020-11-29 06:10

    So here's what I ended up doing:

    I discovered you could pass a function to $scope.$watch. From there, it's pretty straightforward to return the value of the expression you want to watch for changes. It will work exactly like passing a key string for a property on the scope.

    link: function ($scope, $el, $attrs) {
      $scope.$watch(
        function () { return $el[0].childNodes.length; },
        function (newValue, oldValue) {
          if (newValue !== oldValue) {
            // code goes here
          }
        }
      );
    }
    

    I am watching childNodes, not children, because the childNodes list holds elements as well as text nodes and comments. This is priceless because Angular uses comment placeholders for directives like ng-repeat, ng-if, ng-switch and ng-include which perform transclusion and alter the DOM, while children only holds elements.

    0 讨论(0)
  • 2020-11-29 06:13

    If you need to watch for any changes deeper in the element's dom, MutationObserver is the way to go :

    .directive('myDirective', function() {
        return {
            ...
            link: function(scope, element, attrs) {
                var observer = new MutationObserver(function(mutations) {
                    // your code here ...
                });
                observer.observe(element[0], {
                    childList: true,
                    subtree: true
                });
            }
        };
    });
    
    0 讨论(0)
  • 2020-11-29 06:29

    You could try to compile the directive contents first inside your link function. For example:

    angular.module('myApp').directive('autoCarousel', ['$compile', function ($compile) {
    
        return {
            templateUrl: 'views/auto-carousel.html',
            restrict: 'A',
            replace: true,
            link: function (scope, element, attr) {
                $compile(element.contents())(scope);
    
                // your code goes here
            }
        }
    }]);
    
    0 讨论(0)
  • 2020-11-29 06:34

    Although I don't think it is with angular's recommendations, you could use ng-init which fires upon the initialization of the element:

    <ul class="unstyled" auto-carousel>
        <li class="slide" ng-if="name" ng-init="recheck()">{{name}}</li>
        <li class="slide" ng-if="email" ng-init="recheck()">{{email}}</li>
    </ul>
    
    0 讨论(0)
  • 2020-11-29 06:35

    I created a directive module for this angular-dom-events

    In your case you could

        <ul class="unstyled" auto-carousel>
          <li class="slide" ng-if="name" dom-on-create="nameCreated()">{{name}}</li>
          <li class="slide" ng-if="email" dom-on-destroy="emailDestroyed()">{{email}}</li>
        </ul>
    

    Currently only supports dom-on-create and dom-on-destroy, but has better performance then the accepted answer because it will only fire once for each dom event, rather than repeatedly check the $watch callback.

    0 讨论(0)
提交回复
热议问题