Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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 pass configuration to the directive. The thing is that you can observe each attribute separately and fire callback several times.

In the example we have a directive without isolated scope which observs two attributes: name and surname. After any change action callback is fired:

html

<button ng-click="name='John';surname='Brown'">Change all params</button>
<div person name="{{name}}" surname="{{surname}}"></div>

js

angular.module('app', []).

directive('person', function() {
  return {
    restrict: 'A',
    link: function($scope, $elem, $attrs) {
        var action = function() {
          $elem.append('name: ' + $attrs.name + '<br/> surname: ' + $attrs.surname+'<br/><br/>');
        }
        $attrs.$observe('name', action);
        $attrs.$observe('surname', action);
    }
 }
});

Plunker here.

So the effect is that after changing name and surname during one click, action callback is fired twice:

name: 
surname: Brown

name: John
surname: Brown

So the question is: can action be fired only once with both name and surname values changed?

like image 712
kseb Avatar asked Oct 17 '13 20:10

kseb


1 Answers

You can use $watch to evaluate a custom function rather than a specific model.

i.e.

$scope.$watch(function () {
  return [$attrs.name, $attrs.surname];
}, action, true);

That will be run on all $digest cycles, and if $watch detects the return array (or however you want to structure your function's return value) doesn't match the old value, the callback argument to $watch will fire. If you do use an object as the return value though, make sure to leave the true value in for the last argument to $watch so that $watch will do a deep compare.

like image 127
cmw Avatar answered Oct 22 '22 18:10

cmw