$observe multiple attributes at the same time and fire callback only once

前端 未结 5 1722
灰色年华
灰色年华 2021-02-19 20:38

I wonder is it possible to execute some callback only once after evaluation all (or only some) attributes of directive (without isolated scope). Attributes are really great to p

5条回答
  •  感情败类
    2021-02-19 21:24

    So, I've ended up with my own implementation of observeAll method, which can wait for several changes of attributes during one call stack. It works however I'm not sure about performance.

    Solution of @cmw seems to be simpler but performance can suffer for large number of parameters and multiple $digest phase runs, when object equality is evaluated many many times. However I decided to accept his answer.

    Below you can find my approach:

    angular.module('utils.observeAll', []).
    
    factory('observeAll', ['$rootScope', function($rootScope) {
        return function($attrs, callback) {
            var o = {}, 
                callQueued = false, 
                args = arguments,
    
                observe = function(attr) {
                    $attrs.$observe(attr, function(value) {
                        o[attr] = value;
                        if (!callQueued) {
                            callQueued = true;
                            $rootScope.$evalAsync(function() {
                                var argArr = [];
                                for(var i = 2, max = args.length; i < max; i++) {
                                    var attr = args[i];
                                    argArr.push(o[attr]);
                                }
                                callback.apply(null, argArr);
                                callQueued = false;
                            });
                        }
                    });
                };
    
            for(var i = 2, max = args.length; i < max; i++) {
                var attr = args[i];
                if ($attrs.$attr[attr])
                    observe(attr);
            }
        };
    }]);
    

    And you can use it in your directive:

    angular.module('app', ['utils.observeAll']).
    
    directive('person', ['observeAll', function(observeAll) {
      return {
        restrict: 'A',
        link: function($scope, $elem, $attrs) {
            var action = function() {
              $elem.append('name: ' + $attrs.name + '
    surname: ' + $attrs.surname+'

    '); } observeAll($attrs, action, 'name', 'surname'); } } }]);

    Plunker here

提交回复
热议问题