2

I've something like below in DOM:

 <div ng-if="variant"
    ng-include="'size-picker.html'">
 </div>

And in controller:

$scope.variant = false;
// after some unknown time there may be:
$scope.variant = true;

I wanted to show that div when variant is true. So,

$scope.variant will start by false. After some time it may/may not become true. When $scope.variant became true it's never gonna change it's value. So what I want is one-time bind that ng-if once $scope.variant is true.

An approach like:

<div ng-if="::variant"
    ng-include="'size-picker.html'">
</div>

will stop binding when it's false.

I can achieve it by stop assigning false to variant in the first time, but it's not possible in my case.

How can I unbind the ng-if when variant is true?

Asim K T
  • 12,493
  • 9
  • 67
  • 85

2 Answers2

2

The docs say:

One-time expressions will stop recalculating once they are stable, which happens after the first digest if the expression result is a non-undefined value.

So you could start with an undefined value.

K Scandrett
  • 15,287
  • 4
  • 33
  • 59
  • In my case, It will start with false. It's a huge codebase. I have limits to do that. – Asim K T Oct 18 '16 at 05:28
  • 1
    In case Sravan's answer doesn't work for your specific case, you could use a different undefined variable for the ngIf, and then monitor `variant`'s state, updating that variable appropriately. Not optimal, but with difficult constraints sometimes that's the best we can manage – K Scandrett Oct 18 '16 at 06:14
  • That's a nice way doing that. – Asim K T Oct 18 '16 at 06:53
2

You can use $watch, to unregister a binding or a scope

$watch returns a deregistration function.

You can unregister a $watch with the function returned by the $watch call:

var unwatch = $scope.$watch('variant', function(newValue, oldValue) {
    if(newValue == true)
    {
        unwatch();
    }
});

So, once your variant becomes true, the watch on it is removed, and the binding gets stopped.

var app = angular.module( "Demo", [] );

app.controller(
  "AppController",
  function( $scope ) {
    $scope.count = 0;
    $scope.after_unwatch = false;

    var unbindWatcher = $scope.$watch(
      "count",
      function( count ) {
        alert( "Watching click count." );
        if ( count >= 5 ) {
          $scope.after_unwatch = true;
          unbindWatcher();
        }

      }
    );


  
    $scope.incrementCount = function() {
      $scope.count++;
    };

  }
);
<html>
<body>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script>
  <div  ng-app="Demo" ng-controller="AppController">
    <h1>
      Unbinding $watch() Listeners In AngularJS
    </h1>

    <p>
      <a ng-click="incrementCount()">Click it for five times, and after that watch on `count` is removed.</a>
      &raquo;

    </p>

    <p ng-show="after_unwatch">
      <em>The watch on click is removed.</a>
    </p>
  </div>
 </body>
</html> 

Run this code

Here is a plunker

Sravan
  • 16,897
  • 2
  • 24
  • 48