newValue = oldValue when $scope.$watch used in a directive within ng-repeat #11565
Comments
It isn't a problem or a bug: the data never "changes" in your scenario, it just "appears". |
@frfancha thnx so much for helping with the issues here, this is very much appreciated! |
@frfancha Are you sure this is really what is going on? I have the same issue. In my case it is not ngRepeat, but some cached data returned from a promise (so the data isn't changed). The first time $watch fires in the directive newValue is equal to oldValue. I cannot find an explanation to this problem anywhere else. Do you have any reference to angularjs documentation or somwhere else this issue is discussed? |
@stianlp |
@frfancha I found a post on $observe (http://stackoverflow.com/questions/14876112/difference-between-the-observe-and-watch-methods/14907826#14907826) on SO and in my specific case $observe works like a charm. I posted a question on SO about this specific issue because I am curious why $watch is used more commonly than $observe. http://stackoverflow.com/questions/30356803/watch-vs-observe-when-newvalue-oldvalue-angularjs EDIT: Also, why should one use if(newValue === oldValue) return;. It can't imagine it would increase the perfomance that much? If the watcher fires, in almost all situations the value has changed. |
Using Suppose you want to maintain varB = 2 * varA You can do: or: [B] Scenario [B] is easier and has also the following advantage: in scenario [A] you must be sure that between the initialisation of varB and the first call to the watcher nothing has modified varA, otherwise you miss the first change. Scenario [A] is better when computing varB from varA is a heavy process, and you know that the initial value varB is already inline with varA. Then you avoid a first useless recomputation of varB. Again, all this is really a LOT easier to master and understand after reading the first chapter (the first one is freely available) of "Building your own angular JS book" from Tero Parviainen |
@frfancha This is not about varA being inline with varB. It is simply about when does varA appear in the directive. This is the first time I've seen this, and it is probably because varA doesn't change as in other cases where if(n===0) return; works just fine. In my case varA does not change, but the binding that gets varA into the isolated scope does (from ' ' to a number). This is, as you explained in your first answer, simply the value appearing in the directive. The value must appear at some point, but you can never be sure when it will appear, can you? Therefore we must check if the binding into the directive has changed. So, I found $observe and was just wondering why there are no examples out there with the following:
Because it seems to me, that this is what we want in most cases? |
I'm with @stianlp in that most examples I've seen use this technique I've just looked at the ng-bind source code and it seems the canonical way of doing these watches is simply to check if the newvalue is defined
I can't understand how a watch could fire first time with the oldvalue being the same as the newvalue but it is what it is. Although ng-bind is binding on compile, not link... |
Problem is reproduced in the following plunker:
http://plnkr.co/edit/mNN4UuDJZdZZWr52fYar
The $scope.$watch will fire, but newValue is always equal to oldValue, so when we use the following check, it doesn't update.
$scope.$watch("data", function(newVal, oldVal){
if (newVal !== oldVal) {
// data is updated, redraw the directive in my case
// however newVal is always the same as oldVal
}
})
The text was updated successfully, but these errors were encountered: