ng-show ng-if not just in DOM or not

I was thinking I had enough knowledge about the different about ng-if and ng-show which are one adds/removes the containing stuff from the DOM and the latter one just use CSS to hide/show. What’s ironic is I even sometimes use this as an interview question. Today I was bitten by it.

According to the Angualrjs Doc:

The ngIf directive removes or recreates a portion of the DOM tree based on an {expression}. If the expression assigned to ngIf evaluates to a false value then the element is removed from the DOM, otherwise a clone of the element is reinserted into the DOM.

 

No problem.

However in the smaller part, there is another important message:

Note that when an element is removed using ngIf its scope is destroyed and a new scope is created when the element is restored. The scope created within ngIf inherits from its parent scope using prototypal inheritance. An important implication of this is if ngModel is used within ngIf to bind to a javascript primitive defined in the parent scope. In this case any modifications made to the variable within the child scope will override (hide) the value in the parent scope.

So ng-if actually uses ‘transclude’, to create a child scope of the parent.

So if you have something like:

 <input type="text" />

and use $scope.myInput in the controller, it is fine. However after you wrap it with ng-if:

<div ng-if="someCondition">
  <input ng-model="myInput" /></div>

your $scope.myInput would not work anymore since now the myInput is in the child scope and based on the prototypical inheritance mechanism in js, you wont be able to get it from child.

solution 1 would be using ng-show so that it is still in the parent scope.

solution2 could be using $parent.myInput as ng-model

solution 3 is to use ‘controller as vm‘ syntax (angualrjs 1.3 onwards) where the ng-model becomes vm.myInput, so when child scope is trying to bind it, it first try to create $watch the myInput on vm object in its own scope, and after not found, it goes up to the parent scope which is the controller scope which is the one we want.

One article about Regular transclusion and element transclusion.

 

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s