12

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 :)

1
  • 2
    I'm guessing here - but I bet ng-if creates its own child scope. Commented Feb 28, 2014 at 15:46

3 Answers 3

27

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.

Sign up to request clarification or add additional context in comments.

4 Comments

Using $parent does work, but it isn't recommended, because it too will break if another scope is added (like if you put another ng-if, or most any ng- directive.) The best answer is to use a setter method, like in the working example in the original post.
@Hylianpuffball The OP is not about what is recommended. It is about why this is happening. The OP already says that using a controller scoped property would work.
I know; comment was for future answer-seekers.
ng-if was the culprit for a similar problem for me as well. I worked around it by using ng-show instead. Not as clean but works as a quick fix when you need it.
7

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!

1 Comment

Confirmed. I checked the angular documentation for ng-if and it does create a new scope inheriting from the parent scope.
0

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

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.