Ajay Kelkar
Ajay Kelkar

Reputation: 143

Angular: ng-show isn't evaluating expression continuously

I am using a variable called activeScope to maintain state and toggle between two forms. This variable changes value when a tab is clicked by invoking changeScope to update.

This change is registered correctly to toggle between the active states of the tab buttons, but the divs form0 and form1 do not toggle at all. From what I see, it seems that I'm not using ng-show correctly as the expression isn't evaluating when the value of activeScope changes.

Here are my tabs -

<ul class="nav navbar-nav navbar-right" ng-controller="SearchScope as scope">
    <li ng-repeat="item in scopes" ng-class="{'active': isScopeActive({{$index}})}"><a href="" ng-click="changeScope($index)">{{item}}</a></li>
</ul> 

I have my markup for the div's as -

<div class="container main-form" ng-controller="SearchScope as scope">
    <div id="form0" ng-show="isScopeActive(0)" ng-controller="SingleIPController as sip">
    ...
    </div>
    <div id="form1" ng-show="isScopeActive(1)">
    ...
    </div>
</div>

The controller code -

app.controller("SearchScope", function($scope) {
    $scope.activeScope = 0;
    $scope.scopes = ['Individual IP Data', 'All IP Data'];

    $scope.isScopeActive = function(index){
        if(index == $scope.activeScope){
            return true;
        } else {
            return false;
        }
    };

    $scope.changeScope = function(index){
        $scope.activeScope = index;
    };
});

app.controller("SingleIPController", function($scope, $http){
    ...
});

Could someone please advise if what I'm doing with ng-show is wrong and the correct way to go about this problem?

Upvotes: 0

Views: 71

Answers (3)

Ajay Kelkar
Ajay Kelkar

Reputation: 143

Solved by following an approach similar to the one at this codepen. It is almost like what I wanted to achieve - Master-Detail pattern.

Markup -

<div class="container" ng-app="tabApp">
    <div class="row" ng-controller="TabController">
        <div class="col-md-2">
            <ul class="nav nav-pills nav-stacked">
            <li ng-class="{ active: isSet(1) }">
                <a href ng-click="setTab(1)">Home</a>
            </li>
            <li ng-class="{ active: isSet(2) }">
                <a href ng-click="setTab(2)">Profile</a>
            </li>
            <li ng-class="{ active: isSet(3) }">
                <a href ng-click="setTab(3)">Messages</a>
            </li>
            </ul>
        </div>
        <div class="col-md-8">
            <div class="jumbotron">
            <div ng-show="isSet(1)">
                <h1>Home page</h1>
                <p>Welcome to the website!</p>
                <p><a class="btn btn-primary btn-lg" role="button">Learn more</a></p>
                </div>
                <div ng-show="isSet(2)">
            <h1>Profile page</h1>
            <p>Profile information</p>
            </div>
            <div ng-show="isSet(3)">
            <h1>Messages</h1>
            <p> Some messages </p>
            </div>
        </div>
    </div>
</div>

Controller -

angular.module('tabApp', [])
.controller('TabController', ['$scope', function($scope) {
    $scope.tab = 1;

    $scope.setTab = function(newTab){
        $scope.tab = newTab;
    };

    $scope.isSet = function(tabNum){
        return $scope.tab === tabNum;
    };
}]);

CSS -

@import "compass/css3";

body {
margin: 15px;
}

/* text recolor */
h1, p, a {
color: #4DC9C9 !important;
}

/* button recolor */
.nav-pills > li.active > a, .btn-primary {
background-color: #6C6C6C !important;
// feeling like it's a rounded corners kind of day
border-color: #6C6C6C !important;
border-radius: 25px; 
}

Upvotes: 0

codtex
codtex

Reputation: 6558

yes this is not the quite right usage of ng-show. Here is a working demo -> https://jsfiddle.net/agm7pmyw/1/

code:

<div id="search-container" ng-controller="SearchScope">

  <ul class="nav navbar-nav navbar-right">
    <li ng-repeat="item in scopes" ng-class="{'active' : $index == activeScope}">
      <a href="" ng-click="changeScope($index)">{{item}}</a>
    </li>
  </ul>

  <div class="container main-form">
    <div id="form0" ng-show="activeScope == 0" ng-controller="SingleIPController as sip">
      Scope 1
    </div>
  </div>

  <div class="container main-form">
    <div id="form1" ng-show="activeScope == 1" ng-controller="SingleIPController as sip">
      Scope 2
    </div>
  </div>

</div>

script:

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

app.controller("SearchScope", function($scope) {
  $scope.activeScope = 0;
  $scope.scopes = ['Individual IP Data', 'All IP Data'];

  $scope.isScopeActive = function(index) {
    if (index == $scope.activeScope) {
      return true;
    } else {
      return false;
    }
  };

  $scope.changeScope = function(index) {
    console.log('changing scope to ' + index);
    $scope.activeScope = index;
  };
});

app.controller("SingleIPController", function($scope, $http) {

});

css:

.active{
  color:red
}

I did change your markup a little bit, you can play with the demo.

Cheers!

Upvotes: 2

Avantika Saini
Avantika Saini

Reputation: 792

ng-show does not call a function rather evaluates the expression there itself. Hence, modify your code accordingly.

In your controller create a boolean variable which keeps track of the selected type(0=> false, 1=>true). Inside your view, check this vvariable using ng-show to show or hide the form accordingly.

Controller Code :

$scope.showForm1 = false;
$scope.changeScope = function(index){
    if(index == 0)
        $scope.showForm1 = false;
    else
        $scope.showForm1 = true;
};

In your view:

<div class="container main-form" ng-controller="SearchScope as scope">
<div id="form0" ng-show="!showForm1" ng-controller="SingleIPController as sip">
...
  </div>
</div>

<div class="container main-form" ng-controller="SearchScope as scope">
  <div id="form1" ng-show="showForm1" ng-controller="SingleIPController as sip">
...
  </div>
</div>

Upvotes: 1

Related Questions