I have an HTML table and want to sort my records ($scope.records
in ctrl) by clicking on table headers ($scope.headers
in ctrl),
Can anyone explain why does that work:
<th>
<a ng-click="sortColumn=headers[0];reverse=!reverse">{{ headers[0] }}</a>
</th>
<th>
<a ng-click="sortColumn=headers[1];reverse=!reverse">{{ headers[1] }}</a>
</th>
And that doesn't:
<th ng-repeat="header in headers">
<a ng-click="sortColumn=headers[$index];reverse=!reverse">{{ headers[$index] }}</a>
</th>
Here is the code for the records:
<tr ng-repeat="arr in records | orderBy:sortColumn:reverse">
<td ng-repeat="val in arr" ng-bind-html-unsafe="arr[headers[$index]]</td>
</tr>
I have 58 columns in my table so would be much better to loop through the table headers...
As David suggested this is likely scope related. Since ngRepeat creates a new scope your ngClick
is setting the sortColumn
and reverse
in its own child scope for each column header.
One way around this to ensure you are modifying the values in the same scope would be to create a function on the scope and call that in your ngClick passing in the index:
$scope.toggleSort = function(index) {
if($scope.sortColumn === $scope.headers[index]){
$scope.reverse = !$scope.reverse;
}
$scope.sortColumn = $scope.headers[index];
}
with this as your markup:
<th ng-repeat="header in headers">
<a ng-click="toggleSort($index)">{{ headers[$index] }}</a>
</th>
Here is a fiddle with an example.
Another option would be to bind to a non-primitive type like this (the child scopes will be accessing the same object):
$scope.columnSort = { sortColumn: 'col1', reverse: false };
with this as your markup:
<th ng-repeat="header in headers">
<a ng-click="columnSort.sortColumn=headers[$index];columnSort.reverse=!columnSort.reverse">{{ headers[$index] }}</a>
</th>
Here is a fiddle with an example.
Extending Gloopy's answer, yet another option is to modify the parent's properties in the ng-repeat for the primitive types:
<a ng-click="$parent.sortColumn=headers[$index];$parent.reverse=!$parent.reverse">{{ headers[$index] }}
Here is a fiddle.
Note however that $parent is not a documented property of scope, so this is somewhat of a hack, so use at your own risk.
I wish AngularJS had a better way of dealing with these "inner scopes" that are created by ng-repeat, ng-switch, etc. because quite often we need to modify parent scope properties that are primitives.
See also Gloopy's insightful comment about scope inheritance as it relates to primitives and non-primitives here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With