30

If I have a view that does:

<div ng-repeat="foo in foos">
  <p ng-if="bar">omg lol</p>
  <p ng-if="!bar">lol omg</p>
</div>

I am actually creating (2 * foos.length) + 1 $$watchers, which is really not good. I have found several sources online that say you can do ng-if="::bar", but the number of watchers does not change when I do that. Is there a way to force ng-if to be a one time binding?

It is really, really dumb to have to do:

<div ng-repeat="foo in foos" ng-if="bar">
  <p>omg lol</p>
</div>
<div ng-repeat="foo in foos" ng-if="!bar">
  <p>lol omg</p>
</div>

Which I believe will give me something like 4 $$watchers instead... So I am looking for an alternative to avoid having to be silly like that.

PSL
  • 123,204
  • 21
  • 253
  • 243
patrick
  • 9,290
  • 13
  • 61
  • 112
  • :: is one time binding. Just that it wil have a temporary watch created initially and then removed once value is assigned to the bound property. Do you have a proof plunker? – PSL Jun 18 '15 at 00:03
  • 1
    Yes, here is a plunker showing that 2 seconds after the dom has been rendered, the $$watcher count is 2000 just from an ng-if... http://plnkr.co/edit/JgP3lRyuSoSPQNIgR8Ri?p=preview – patrick Jun 18 '15 at 00:46
  • 2
    What i see is [`
  • {{ ::item }}
  • `](http://plnkr.co/edit/Eg9t3X?p=preview) watcher count ==> 2 [without prefixing `lol` with `::` it is 1002](http://plnkr.co/edit/cwAun9?p=preview). What say you? – PSL Jun 18 '15 at 00:47
  • totally confused... what? so you are saying the alert window pops up after the timeout on your browser says 2 watchers? – patrick Jun 18 '15 at 00:51
  • Yup..ofcourse. I tried in chrome and FF (should not matter though). Click on those 2 links in my comment. Just imagine that was the whole purpose of using 1-time binding and motivation for anybody (atleast i did :) ) to migrate when it released to get over the hangover from bindonce. – PSL Jun 18 '15 at 00:52
  • 1
    I apologize, I thought I had saved the version with ::lol, not just lol. Well, this is very odd because this is not the behavior I am experiencing with my app, the :: prefixes in my ng-ifs are doing absolutely nothing and my watcher count is in the thousands, so I think I need to investigate further. – patrick Jun 18 '15 at 00:54
  • That could well be because in your app actual data might be bound in deferred manner (via ajax call or so). Until then these watchers will be there (they are removed the moment it gets a non-undefined value). If it does not do that one time binding would have been a failure for deferred data binding approaches. – PSL Jun 18 '15 at 00:56
  • Ah.. no i just figured out what it is! My directive uses configuration to say whether or not to render things in the view's ng-repeater... And some of the configuration options are false by default simply by not supplying the values. It appears if scope.lol is undefined, then ::lol still adds watchers. http://plnkr.co/edit/Gdb893nV4JdzeCDtnkyZ?p=preview – patrick Jun 18 '15 at 01:00
  • This is expected. See my prev comment (the stuff in the bracket). You are not setting anything on lol. And if you expect lol to be set during some operation this will not happen right. If that condition fails set it to false. You just need to make sure if you are setting a one-time binding you ultimately end up setting some value (even null is a value which is falsy) to it. Which is not big of a deal if you get the advantage of clearing unwanted watches. – PSL Jun 18 '15 at 01:03
  • Thank you for the help. You should post an answer so I can accept it. – patrick Jun 18 '15 at 01:09
  • You are welcome. Glad i was able to clarify.. Sure i will expand my comments to an answer. Thx! – PSL Jun 18 '15 at 01:11