Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AngularJS directive needs to watch two properties

I'm making a game in Angular. Each player object has an x and a y property. Whenever the player moves, I want to start a timer that cycles through a couple background positions in the sprite sheet.

I thought I would do this with a directive. The problem is that directives normally only let you set one expression to watch:

// "test" directive
module.directive("test", function() {
  return function(scope, element, attrs) {
    scope.$watch(attrs.test, function(value) {
      // do something when it changes
    })
  }
})

// my template
<div test="name"/>

The nice thing about this approach, is the test directive doesn't have to assume the scope has any particular property. You're telling it what to use when you use the directive.

The problem is that in my case I need to kick something off if either x OR y changes. How can I do this?

<div test="player.x, player.y"/>
<div test="player.x" test-two="player.y"/>

Is there a best way to do this that you can think of? Basically I want to make a directive that does something on a timer if any of several properties change.

like image 392
Sean Clark Hess Avatar asked Nov 11 '12 04:11

Sean Clark Hess


4 Answers

The easiest and most readable solution in my opinion is to use two attributes and simply set up two watches:

// "test" directive
module.directive("test", function() {
  return function(scope, element, attrs) {
    var doStuff = function() {
      console.log(attrs.test);
      console.log(attrs.testTwo);
    }
    scope.$watch(attrs.test, doStuff);
    scope.$watch(attrs.testTwo, doStuff);

  }
})

// my template
<div test test="player1.x" test-two="player1.y" />
like image 152
Pete BD Avatar answered Sep 27 '22 21:09

Pete BD


I would try to use a function in the $watch function.

Here is the plunker

var app = angular.module('plunker', [])
.directive('myDir',function(){
  return {
    restrict:'E',
    template:'<span>X:{{x}}, Y:{{y}}</span>',
    link:function(scope, elm, attrs){
      scope.$watch(function (){
        var location = {};
        location.x = attrs.x;
        location.y = attrs.y;
        return location;
      }, function (newVal,oldVal,scope){
        console.log('change !');
        scope.x = newVal.x;
        scope.y = newVal.y;
      }, true);
    }
  };
});

app.controller('MainCtrl', function($scope) {

});





 <div>X: <input type='text' ng-model='x'/></div>
  <div>Y: <input type='text' ng-model='y'/></div>
  <my-dir x='{{x}}' y='{{y}}'></my-dir>
like image 41
maxisam Avatar answered Sep 27 '22 21:09

maxisam


There is some work arounds for this

Watch multiple $scope attributes

https://groups.google.com/forum/?fromgroups=#!topic/angular/yInmKjlrjzI

like image 44
Everton Yoshitani Avatar answered Sep 27 '22 20:09

Everton Yoshitani


scope.$watch(function () {
  return [attrs.test, attrs.test-two];
}, function(value) {
      // do something when it changes
}, true);

see this link

you can also use $watchGroup - see this link

like image 42
Omid-RH Avatar answered Sep 27 '22 22:09

Omid-RH