Turns out that angular $watch statements will always fire once to
"initialize" the 'watch' statement. The officially recommended workaround,
should you not want this behavior, is to use an object identity check to
compare the values, ie:
$scope.$watch 'allProviders', (selected, prior) ->
return if selected is prior
...In JS, the === is the same as Coffeescripts is operator.
Note, this has nothing to do with the third argument to $watch which tells
the $watch command to compare on identity vs equality. The initialization
behavior described above will occur regardless of this setting.
From the docs:
After a watcher is registered with the scope, the listener fn is called asynchronously (via $evalAsync) to initialize the watcher. In rare cases, this is undesirable because the listener is called when the result of watchExpression didn't change. To detect this scenario within the listener fn, you can compare the newVal and oldVal. If these two values are identical (===) then the listener was called due to initialization.
- Angularjs docs for
$watch
The guard and the
identity vs equalitydescribed above are completely independent. Regardless of the$watchmode used (identity or equality), the $watch statement will be executed once on creation to initialize it.In both cases, you want to use an identity check (
isin coffeescript, or===in JS) for the guard clause.