moosefetcher
moosefetcher

Reputation: 1901

Getting ng-class to vary over an interating ng-repeat

I'm setting up a set of page indicators and I want only the indicator that corresponds to the currently viewed page to have the class 'active' applied to it.
I've set up a controller to determine which indicator should have the 'active' class applied, using ng-class in the html:

<div class="progress-buttons" ng-controller="progressButtonCtrl">
    <div ng-repeat="(skey,page) in pages" class="button" ng-class="ctrlClass" ng-attr-id="{{'nav-'+(skey+1)}}">
         <div ng-switch="page.titletext || '_undefined_'" >      
              <span ng-switch-when="_undefined_">{{skey+1}}</span>
         </div>
    </div>
</div>

And here's the controller...

app.controller('progressButtonCtrl', ['$scope', '$routeParams', '$http', 'content', function($scope, $routeParams, $http, content) {

    function initScope() {
        $scope.pageId = $routeParams.pageId; 
        $scope.ctrlClass = "";

        content.success(function(data) {

            $scope.pages = data;
            angular.forEach($scope.pages, function(value, key) {
                console.log("$scope.pageId = "+$scope.pageId);
                console.log("page id (value.id) = "+value.id);
                if ($scope.pageId == value.id) {
                    console.log("active class applied...");
                    $scope.ctrlClass = "active";
                }
            });
        });
    }

    initScope();

}]);

I've 'console logged' out the id value of the current page and the id values of all pages; They output as 1 and 1,2,3 as I'd expect. But, despite 'active class applied...' only getting output once, the 'active' class is applied to all the indicators. I'm guessing I need a unique ng-class identifier per indicator, but how can I do that in an ng-repeat, when the number of instances will vary?

What should I be doing differently to apply the 'active' class just to the currently viewed page?

Thanks.

Upvotes: 0

Views: 28

Answers (1)

krutkowski86
krutkowski86

Reputation: 1083

You should have assigned it to the specific array (pages) element instead of scope var.

angular.forEach($scope.pages, function(value, key) {
   console.log("$scope.pageId = "+$scope.pageId);
   console.log("page id (value.id) = "+value.id);
   if ($scope.pageId == value.id) {
      console.log("active class applied...");
      value.class = "active";
   }
});

and your HTML:

<div ng-repeat="(skey,page) in pages" class="button" ng-class="page.class" ng-attr-id="{{'nav-'+(skey+1)}}">
   <div ng-switch="page.titletext || '_undefined_'" >      
      <span ng-switch-when="_undefined_">{{skey+1}}</span>
   </div>
</div>

I would recommend you doing it this way:

app.controller('progressButtonCtrl', ['$scope', '$routeParams', '$http', 'content', function($scope, $routeParams, $http, content) {

    function initScope() {
        $scope.pageId = $routeParams.pageId;

        content.success(function(data) {
            $scope.pages = data;
        });
    }

    initScope();

}]);

HTML:

<div class="progress-buttons" ng-controller="progressButtonCtrl">
    <div ng-repeat="(skey,page) in pages" class="button" ng-class="::{'active':pageId == page.id}" id="::{{'nav-'+(skey+1)}}">
         <div ng-switch="page.titletext || '_undefined_'" >      
              <span ng-switch-when="_undefined_">{{skey+1}}</span>
         </div>
    </div>
</div>

ng-class="::{'active':pageId == page.id}" the :: sign at the begining means one-way data binding. You could read about it more here https://toddmotto.com/angular-one-time-binding-syntax/

Upvotes: 1

Related Questions