Angular JS: ng-click scope set doesn't work in ng-if

All we need is an easy explanation of the problem, so here it is.

Today, I have seen a bug in angularjs:

When you try to set a scope value directly in a ng-click, it doesn’t work when your ng-click is in a ng-if which test the same scope value -> http://jsfiddle.net/9j2TL/26/

angular.module('test', [])
.controller('testCtrl', function($scope) {
    $scope.step = 1;

    $scope.setStep = function(step) {
         $scope.step = step;  
    };
});

<div ng-app="test">
<div ng-controller="testCtrl">
    <ul class="timeline">
        <li>
            <div class="block-submit">
                <button class="btn btn-primary btn-lg" ng-click="step = 2">Without ngif block</button>
            </div>
        </li>

        <li ng-if="step > 1">
            <div class="block-submit">
                <button class="btn btn-primary btn-lg" ng-click="step = 3">with ngif block</button>
            </div>
        </li>

        <li ng-if="step > 1">
            <div class="block-submit">
                <button class="btn btn-primary btn-lg" ng-click="setStep(3)">With ngif block and scope function</button>
            </div>
        </li>
    </ul>
    <p>
        step value : {{ step }}
    </p>
</div>
</div>

To solve it, you should create a scope function…

If somebody have a explication for this problem, I would be happy to understand it !

thx 🙂

How to solve :

I know you bored from this bug, So we are here to help you! Take a deep breath and look at the explanation of your problem. We have many solutions to this problem, But we recommend you to use the first method because it is tested & true method that will 100% work for you.

Method 1

I don’t think this is a bug. You are just auto-creating properties and confusing scopes in the view.

Updated Fiddler.

This does work:

<li ng-if="step > 1">
    <div class="block-submit">
        <button class="btn btn-primary btn-lg" ng-click="$parent.step = 3">with ngif block</button>
    </div>
</li>

This is happening because self inside of the ng-if is creating a new scope.

Method 2

It’s not a bug, i think that “ng-if” creates its an own scope, so when you do here: “step = 3”, you’re creating and assign this variable in a separate scope than your controller

<li ng-if="step > 1">
     <div class="block-submit">
                <button class="btn btn-primary btn-lg" ng-click="step = 3">with ngif block</button>
     </div>
</li>

And here you still in a separate scope but when you call a function, probably angular will look for this function inside your scope, but when angular doesn’t find it, it will look for the function in your parent scope, and when find it, it will assign to your step parent scope variable, that’s why it work here and not in your code above.

<li ng-if="step > 1">
       <div class="block-submit">
                <button class="btn btn-primary btn-lg" ng-click="setStep(3)">With ngif block and scope function</button>
       </div>
</li>

I think that it is what is happening, if anyone could confirm it would be great!

Method 3

ng-if creates its own scope, which can complicate things.

Changing ng-if to ng-show should solve the problem.

Note: Use and implement method 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply