2

This is my angular code.. (to describe the problem I'm getting is that the nested ng-repeat for buttons repeats is behavior (when clicked) to all the "jobs" listed..

    <div class="row" ng-repeat="job in jobs">
        <div class="btn-group btn-group-justified" role="group">
             <div class="btn-group" role="group" ng-repeat="status in job.statuscollection">
                   <button type="button" class="btn btn-default" ng-class="{ 'btn-info': $index == selectedIndex }" ng-click="itemClicked($index)">{{status.name}}</button>
             </div>
        </div>
    </div>

Here's my js code..

    $scope.jobs = [
    {
        _id: new Date().toISOString(),
        statuscollection: [
            { name: "Off-Site"},
            { name: "Enroute" },
            { name: "On-Site" },
        ]
        docType: "job",
    },
    {
        _id: new Date().toISOString(),
        statuscollection: [
            { name: "Off-Site"},
            { name: "Enroute" },
            { name: "On-Site" },
        ]
        docType: "job",
    }];

This here's my ng-click function..

    $scope.itemClicked = function ($index) {
         $scope.selectedIndex = $index;
         console.log($scope.jobs[$index]);
    }

I have more than just one job, I included only one here into the code to have less of it. but when the browser generates this data in the correct way, clicking on one of the "job's" buttons does the same thing for each job.

Meaning, if I click the button "on-site" for one job, it is duplicated for all the jobs.. how can I make it so that clicking just one of the job's buttons does it only for that job, and not all of them?

LatentDenis
  • 2,839
  • 12
  • 48
  • 99

2 Answers2

1

Use $parent.$index instead of $index to refer to the outer ng-repeated loop (the job loop, that is):

<button type="button" class="btn btn-default" ng-class="{ 'btn-info': $parent.index == selectedIndex }" ng-click="itemClicked($parent.$index)">{{status.name}}</button>

$index is the index of the inner loop.

$parent.$index is the index of the outer loop.

Tarun Dugar
  • 8,921
  • 8
  • 42
  • 79
  • **$parent.index** should be **$parent.$index** ? but either way, this doesn't have the desired effect.. this gives the class "btn-info to each statuscollection.name button per job. so that all three buttons inside a single job are selected, all the other jobs are left without a selected job. – LatentDenis Nov 23 '15 at 18:03
1

The proper Angular approach to track indices across multiple ngRepeats is to use ngInit to create a local variable that aliases $index for each instance of ngRepeat. Using $parent to acquire its $index position is generally discouraged.

And in the example below, we have two ngRepeats and therefore two aliased index variables: outerIndex and innerIndex:

  <tbody ng-repeat="country in countries" ng-init="outerIndex = $index">
    <tr ng-repeat="city in country.cities" ng-init="innerIndex = $index">
      <td>{{city}}</td>
      <td>{{country.name}}</td>
      <td>({{outerIndex}}, {{innerIndex}})</td>
    </tr>
  </tbody>

Plunker: http://plnkr.co/edit/VA1XWWrG3pghEcWli06F


Final Edit

After understanding more of the context behind the question, it actually makes more sense for the OP to set an isActive property on the selected object instead attempting to track and match indices. That said the approach noted above is still valid and applicable for tracking indices across multiple ngRepeats

 $scope.itemClicked = function (status, job) {
   if (status.isActive) {
     status.isActive = false;
   } else {
     angular.forEach(job.statuscollection, function(status) {
       status.isActive = false;
     });
     status.isActive = true;
   }
 }

Updated plunker: http://plnkr.co/edit/v70fY30PjoTXCrhOPVZB

lux
  • 8,315
  • 7
  • 36
  • 49
  • 1
    given this approach, should the $scope.selectedIndex inside the itemclicked function become $scope.outerindex? – LatentDenis Nov 23 '15 at 18:08
  • Yeah, if that's the variable you eventually want access to; I just reread your description, in which you stated you will have more `job` objects, not just one. So yes, if you want the index of the `job`, then you'll want to pass `outerIndex` to the click function. – lux Nov 23 '15 at 18:11
  • Lux, I've tried your approach of replacing the ng-click function to pass in outerIndex now, and the second line of my itemClicked function, from this: **$scope.selectedIndex = $index;** to this: **$scope.outerIndex = $index;**, but the class still doesn't change when clicked – LatentDenis Nov 23 '15 at 18:28
  • The plunker I provided didn't actually have any CSS to apply, so I just updated it: http://plnkr.co/edit/v70fY30PjoTXCrhOPVZB – lux Nov 23 '15 at 18:32
  • Let me know if exact behavior you are expecting, but in this case, we can see that the class does not apply to whichever button we click. Is this the3 expectation? – lux Nov 23 '15 at 18:32
  • see if by adding an extra job (I've editted my js code above to have two entities for job), you'll see what I mean. the desired effect is for example, you have two Outers containing the 3 Inners. If you click on one of the Inner buttons in the first "job" the class changes on that Inner button for that first outer job (doesn't change the second job), and vice versa can be changed on the second job to any three inner buttons without changing anything on the first job. – LatentDenis Nov 23 '15 at 18:44
  • here's a srnshot for more comprehensive explanation.. [link](http://s27.postimg.org/sm4b5hhnn/Screenshot_7.png) – LatentDenis Nov 23 '15 at 18:50