Search code examples
angularjsangularjs-scopeangularjs-ng-repeatangularjs-controllerng-class

Angularjs: Using ng-class to add a class to completed progress step


I am trying to add a class to a completed step indicator on the progress bar but cannot figure out how to do it. A step is completed when a button is clicked on the page and takes the user to the next page (next step). So when this happens, I want to add a class to the previous step indicator on the progress bar that will indicate it was completed. Here is where I want it to happen: data-ng-class="{checked:isChecked($index)}". The function doesn't necessarily have to pass $index, I was just taking a stab at it. I am able to do this for the active progress step, just not a previous one. I'm racking my brain trying to figure it out but have a feeling I am overthinking it.

<div data-ng-controller="ProgressBarCtrl">
  <div class="progress-bar">
    <ul>
      <li ng-repeat="step in steps" data-ng-class="{active:isActive('{[{ step.path }]}')}">
        <div class="progress-content">
          <span data-ng-class="{checked:isChecked($index)}" class="number-circle">{[{ step.step }]}</span>
          <span class="progress-copy">{[{ step.desc }]}</span>
        </div>
      </li>
    </ul>
  </div>
</div>


angular.module('progressBar', [])

.config(['$locationProvider', function($locationProvider){
  $locationProvider.html5Mode(true);
  }])

.controller("ProgressBarCtrl", ['$scope', '$location', function($scope, $location) {

  $scope.isActive = function(route) {
    // console.log('route ' + route);
    // console.log('path ' + $location.path());
    return route === $location.path();
  }

  $scope.steps = [
    { "step" : 1, "desc" : "Choose Plan", "path" : "/offers" },
    { "step" : 2, "desc" : "Customize", "path" : "/customize"},
    { "step" : 3, "desc" : "My Info", "path" : "/customer_details"},
    { "step" : 4, "desc" : "Installation"},
    { "step" : 5, "desc" : "Payment"}
  ]

  $scope.isChecked = function($index) {
    // Not sure what to do here or if this even the right approach
  }

}]);

Thanks in advance.


Solution

  • You need to keep track of the current step's index and compare it to the $index value.

    // ...
    
    .controller("ProgressBarCtrl", ['$scope', '$location', function($scope, $location) {
    
      $scope.currentIndex = 0; // default to 0
    
      $scope.isActive = function(route) {
        // console.log('route ' + route);
        // console.log('path ' + $location.path());
        if(route === $location.path()){
          // set current index value here
          angular.forEach($scope.steps, function(step,i){
            if(route === step.path){
              $scope.currentIndex = i;
            }
          });
          return true;
        } else {
          return false;
        }
      };
    
      $scope.steps = [
        { "step" : 1, "desc" : "Choose Plan", "path" : "/offers" },
        { "step" : 2, "desc" : "Customize", "path" : "/customize"},
        { "step" : 3, "desc" : "My Info", "path" : "/customer_details"},
        { "step" : 4, "desc" : "Installation"},
        { "step" : 5, "desc" : "Payment"}
      ];
    
      $scope.isChecked = function($index) {
        return $index < $scope.currentIndex;
      };
    
    }]);
    

    Haven't tested this code, but the general idea should work.