Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

one-time binding with ng-if in angular?

Tags:

angularjs

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.

like image 775
patrick Avatar asked Jun 17 '15 23:06

patrick


People also ask

Can we use ngIf and Ng-show together?

ng-if is better in this regard. Using it in place of ng-show will prevent the heavy content from being rendered in the first place if the expression is false. However, its strength is also its weakness, because if the user hides the chart and then shows it again, the content is rendered from scratch each time.

What is the use of NG-if?

Definition and Usage The ng-if directive removes the HTML element if the expression evaluates to false. If the if statement evaluates to true, a copy of the Element is added in the DOM.

Which is better Ng-if or NG-show?

ng-if can only render data whenever the condition is true. It doesn't have any rendered data until the condition is true. ng-show can show and hide the rendered data, that is, it always kept the rendered data and show or hide on the basis of that directives.


1 Answers

Just extending my comments to answer.

Angular 1.3 one-time binding syntax (::) indeed will remove unnecessary watches. Just that you need to measure the watches a while after you set the relevant data. Here is why it is. When you set a one-time bound property on the view, angular will set a temporary watch on it until it gets a defined value, i.e anything but undefined. This approach is there for a reason - in order to support the bound values that are populated via a deferred operation like ajax call, timeout, promise chain resolution etc.. Without this :: will not work successfully on anything but pre-populated bound values.

So just make sure that you set some value at some point in time to the one-time bound values. Don't let it remain undefined.

Say when you have a condition <div ng-if="::lol"></div> repeated 100 times. Just make sure when you bind the value to the repeater or some operation that determines the status of lol even if that operation fails (say a ajax call error) still set a value (even null is also a value in javascript) to it. Watches will be removed after the upcoming digest cycle which renders the respective DOM bindings.

In your specific plunker you could as well do:

<ul ng-repeat="item in items"  ng-if="::lol">   <li>{{ ::item }}</li> </ul> 

instead of

<ul ng-repeat="item in items">   <li ng-if="::lol">{{ ::item }}</li> </ul> 
like image 186
PSL Avatar answered Sep 19 '22 03:09

PSL