AlexP
AlexP

Reputation: 459

Angular ng-repeat value set

I use ng-repeat to construct table with radio buttons. The idea is to assign to each radio value the position of the object inside the original array (before ordering). When I use $index it assigns position in the ordered array and not original one. How to assign the right index,original one?

<tr class="restTable" data-ng-repeat="person in persons|orderBy:'name'">
<td> {{ person.name}}</td>
<td> <input type="radio" name="radio" ng-model="$parent.selectedPerson" value="{{$index}}"/></td>
</tr>

Upvotes: 1

Views: 4170

Answers (2)

Alon Eitan
Alon Eitan

Reputation: 12025

As I wrote in the comment:

$index is relative to to the current element in the loop and since you are sorting the array then you need to save a reference on the object itself from the directive (You can use person.id for example (If you have a unique id for each person).

You can save a reference to the selected person via ngValue

angular.module('app', []).controller('ctrl', function($scope) { 
  $scope.selected = { person: null };
  $scope.persons = [{id: 1, name: "person1"}, {id: 2, name: "person2"}, {id: 3, name: "person3"}]; 
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl">
  <table>
    <tr class="restTable" data-ng-repeat="person in persons|orderBy:'name'">
      <td> {{ person.name}}</td>
      <td> <input type="radio" name="radio" ng-model="selected.person" ng-value="person"/></td>
    </tr>
  </table>
  
  <hr>
  <p>Selected Person:</p>
  <pre ng-bind="selected.person | json"></pre>
</div>

Here i'm using the ngValue and saving a reference to the selected object inside the loop. I don't care about the current position of the object because angularjs is making sure the selected person will be available in the controller via $scope.selected.person.

If you want to pre select a person, replace

$scope.selected = { person: null };

With

$scope.selected = { person: $scope.persons[1] };

But don't forget to declare $scope.persons before! Put that line after you declared the array in your controller. Example:

angular.module('app', []).controller('ctrl', function($scope) { 
  $scope.persons = [{id: 1, name: "3person1"}, {id: 2, name: "1person2"}, {id: 3, name: "4person3"}]; 

  $scope.selected = { person: $scope.persons[1] };
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl">
  <table>
    <tr class="restTable" data-ng-repeat="person in persons|orderBy:'name'">
      <td> {{ person.name}}</td>
      <td> <input type="radio" name="radio" ng-model="selected.person" ng-value="person"/></td>
    </tr>
  </table>
  
  <hr>
  <p>Selected Person:</p>
  <pre ng-bind="selected.person | json"></pre>
</div>

Upvotes: 1

Akhlesh
Akhlesh

Reputation: 2399

$index won't work as it represents index of loop, not the index of item in array. So to fix this you could have index property in source or you could write a function to return related index.

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

app.controller('ctrl', ['$scope', function(scope) {

  scope.persons = [{
    name: 'ABC index 0'
  }, {
    name: 'EFG index 1'
  }, {
    name: 'XYX index 2'
  }];

  scope.selectedPerson = "1";
  scope.getIndex = function(item) {
    return scope.persons.indexOf(item);
  }
}])

angular.bootstrap(document.body, ['app']);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-controller="ctrl">
  Selected Person:-
  <pre>{{persons[selectedPerson] | json}}</pre>
  <hr/>
  <table>
    <tr class="restTable" data-ng-repeat="person in persons|orderBy:'name'">
      <td> {{ person.name}}</td>
      <td>
        <input type="radio" name="radio" ng-model="$parent.selectedPerson" value="{{$parent.getIndex(person)}}" />
      </td>
    </tr>
  </table>
</div>

Upvotes: 1

Related Questions