Angular scope not affecting ng-show as expected

526 views Asked by At

I have a question about Angular.js scope.

Firstly I am very new to Angular and I have read the scope documentation and tried to understand it the best I can. I have a feeling my question is similar to this: ng-show not binding as expected

However my example is simpler in nature and I still don't understand what I am missing.

My html is very simple, I have a controller that wraps everything:

<div ng-controller="ApplicationFormController"></div>

Inside this I have sections:

<div ng-controller="ApplicationFormController">
<button ng-click="previous()">previous</button>
<button ng-click="next()">previous</button>
<p> You are on section #1 </p>
    <div class="section1" ng-show="{{ section.id == 1 }}"> Section 1 </div>
    <div class="section2" ng-show="{{ section.id == 2 }}"> Section 2 </div>
    <div class="section3" ng-show="{{ section.id == 3 }}"> Section 3 </div>
</div>

As you can see I intend to show the section when it is applied to the controller.

My application logic is as follows:

app.controller('ApplicationFormController', ['$scope', function($scope) {
    $scope.sections = sections;
    $scope.section = $scope.sections[0];

    $scope.next = function() {
        var index = $scope.sections.map(function(x){
            return x.id;
        }).indexOf($scope.section.id);

        $scope.section = $scope.sections[index+1];
    };
    $scope.previous = function() {
        var index = $scope.sections.map(function(x){
            return x.id;
        }).indexOf($scope.section.id);

        $scope.section = $scope.sections[index-1];
    };

}]);

The sections array is as follows:

var sections = [
    {
        id: 1,
        name: 'Section 1',
        steps: [
            {
                id: 1,
                name: 'Step 1',
            },
            {
                id: 2,
                name: 'Step 2',
            },
            {
                id: 3,
                name: 'Step 3',
            },
        ]
    },
    {
        id: 2,
        name: 'Section 2',
        steps: [
            {
                id: 1,
                name: 'Step 1',
            },
            {
                id: 2,
                name: 'Step 2',
            },
            {
                id: 3,
                name: 'Step 3',
            },
        ]
    }
];

Very simple stuff.

So the issue lies in the showing and hiding.

When I trigger the next or previous event it runs, I can see this because the <p> tag updates with the appropriate id eg: if I press next the p tag will update to reflect:

<p>You are on section #2</p> as expected.

The odd thing is the section that is currently showing doesn't update. Section one in this case will stay visible while section two will stay hidden.

What is preventing the DOM from updating to reflect the current state of the controller.

1

There are 1 answers

1
PSL On BEST ANSWER

That is because ng-show takes an expression upon which a watch is set internally. But you are providing value of expression (boolean string) by using interpolation ({{). So watch never executes afterwards since scope.$watch(attr.ngShow,...) will be evaluating scope['true/false'] instead of actual expression you intended to.

Change:

   <div class="section1" ng-show="{{ section.id == 1 }}"> Section 1 </div>

to

   <div class="section1" ng-show="section.id == 1"> Section 1 </div>

and so on for others too.