1

This has come up while I was trying to change the back color of a li whenever the text changes. From another post I was directed to, I found a method of doing this which looks ideal, and have added to my plunker example.

So, the main bit of code here is in this directive...

 .directive('animateOnChange', function ($timeout) {       
   return function (scope, element, attr) {

     scope.$watch(attr.animateOnChange, function (nv, ov) {
    if (nv != ov) { // change to true and this works
      element.addClass('changed');
      $timeout(function() {
        element.removeClass('changed');
      }, 500); // Could be enhanced to take duration as a parameter
    }
  });
};
})

When you click the button, a property is updated, but we get no color change, as the values of nv and ov at the line if (nv != ov) are always the same (if you replace the nv != ov with just true we can see the color change, which also then occurs at initialisation, which I don't really want.

So the question is why would my old value and new value (ov, nv) always be the same?

Any help greatly appreciated.

Community
  • 1
  • 1
peterc
  • 6,921
  • 9
  • 65
  • 131

2 Answers2

0

So you got an array. To detect changes in array it's better to use $scope.$watchCollection().

You also should use ng-class directive to set and remove classes from DOM elements. If you want to change background color of element you can use

ng-class="{'bg-green': textUpdated}"

Where 'bg-green' is style in your css:

.bg-green{background-color: green;}

And 'textUpdated' is a flag in your model which you set in your 'update' method.

Using ng-class also allows you to use angular animation. Example is at the bottom of ng-class documentation page.

Community
  • 1
  • 1
Denis
  • 747
  • 4
  • 13
  • thanks for that info, I had a look at the $watchCollection, but this look more if I want to watch the whole collection rather than a "deep" watch on each of the elements. I have since noticed two more things 1. I had my ng-repeat in the wrong place, should be on the li, not the ul. After doing this, I have noticed when I update the li text, the whole directive function seems to be called again, not just the watch, as can be seen at this updated [Plunk](http://plnkr.co/edit/j94XoZYyEzPjlDs9U4e7). A breakpoint at the line `var yy = 0;` is hit every time I update the text. – peterc Dec 25 '15 at 03:07
0

I have found a way to get the above working. What I had to do is store an object, rather than just text in the properties collection. I.e. rather than have scope.properties.push("Location A"), I use scope.properties.push(new Property ("Location A")), where all Property does is construct an object with a text property..

 function Property(text){        
    this.text = text;
  }

And in the markup I watch and update this text property..

<div class="carul" ng-repeat="p in properties" animate-on-change="p.text">{{p.text}}</div>

Now ov and nv are only equal for the initialization, and all other update (i.e. by the button press), they contain the expected old and new value.

I am not sure why I need to wrap in an object (not that I am worried about having to), but would be interested if anyone did have a comment as to why.

I also now just use a single <div> rather than a <ul> (not that this had anything to do with the problem, just realized could not see the need for a <ul> here).

Can see the above modifications here.

peterc
  • 6,921
  • 9
  • 65
  • 131