1

I have a little issue on my first AngularJS project. To sum up I have a JSON that I load using a service to create tables.

This JSON looks like this :

[ { id: 5, year: 2018, data: [{id:1, name:"John Doe", age: 28},...] }, ... ]

For each element in my JSON I create a table and I populate each table with each sub-element (data). Then I implemented a sorting system for my table. When I click on one of the th, it sorts data.

Here is a sample of my HTML code :

<table ng-repeat="elem in json">
<thead>
<tr>
<th ng-click="sortData('id')">ID <i ng-class="getSortClass('id')"></i></th>
<th ng-click="sortData('name')">Name <i ng-class="getSortClass('name')"></i></th>
<th ng-click="sortData('age')">Age <i ng-class="getSortClass('age')"></i></th>
<th>....</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="row in elem.data | orderBy:sortColumn:reverseSort">
<td>...</td>
....
</tr>
</tbody>
</table>

Here is a sample of my JS code:

$scope.sortColumn = "name";
$scope.reverseSort = false;

$scope.sortData = function (column) {
    $scope.reverseSort = ($scope.sortColumn == column) ? !$scope.reverseSort : false;
    $scope.sortColumn = column;
}

$scope.getSortClass = function (column) {

if ($scope.sortColumn == column) {
    return $scope.reverseSort
      ? 'fa fa-chevron-down'
      : 'fa fa-chevron-up';
}

return '';
}

It actually works, however the thing is I want each table to be independent of each other. Currently if I sort for instance the "name" column in the first generated table, it also sorts the "name" other tables.

Is there a way to apply the sorting to the table from where the click was made? I thought to add a parameter that would be the id of the table or something of the kind. I didn't try that at for now but is it good idea or is there a proper way to do that?

Thanking you in advance,

3
  • Is each table a separate component / directive or do they by chance share a scope? Commented Nov 2, 2018 at 19:01
  • All the tables are in the same controller. They share the same parent scope. Commented Nov 2, 2018 at 19:07
  • But then your scope.sortcolumn is shared as well, isn't it? That would explain the behavior you describe. Commented Nov 2, 2018 at 19:09

2 Answers 2

3

You want a sort variable for each of your tables, But you are sharing a global variable which every table looks for. There are several solutions. One that come to my mind is to have a list of sort columns and use it for each table:

$scope.sortColumn = [];
$scope.reverseSort = [];

$scope.sortData = function (id, column) {
    $scope.reverseSort[id] = ($scope.sortColumn[id] == column) ? !$scope.reverseSort[id] : false;
    $scope.sortColumn[id] = column;
}

and change your ng-repeat accordingly:

<tr ng-repeat="row in elem.data | orderBy:sortColumn[id]:reverseSort[id]">

and in the same way your $scope.getSortClass method.

also your ng-click becomes this:

<th ng-click="sortData(elem.id, 'id')">
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you for your answer, it works very well, however what if I want to have a default sort, let's say by column "name" (asc). What's the best way to initialize it ? Pre-fill the arrays with n entries ?
you can fill that array, or at the time that you are initializing elem.data array. I would do the latter .
0

Based on the code, it looks like the tables may be sharing one scope, including the sortColumn property. If that's the case, changing it in one table will sort all tables. You can mitigate this by making each table a directive or component with an isolated scope.

I.E. you could have something like

<my-custom-table elem="elem" ng-repeat="elem in json">
</my-custom-table>

And then you would define my-custom like a directive with an isolated scope like so:

angular.module('yourApp').directive('myCustomTable', function () {
  return {
     scope: {
         elem: '='
     },
     link: function(scope){
         scope.getSortClass=function(){…}
         scope.sortData=function(){…}
     },
     templateUrl: 'path_to_my_custom_table.html'
  };
});

And then the template of my_custom_table.html would just be

<table>
   <thead>
     <tr>
     <th ng-click="sortData('id')">ID <i ng-class="getSortClass('id')"></i></th>
     <th ng-click="sortData('name')">Name <i ng-     class="getSortClass('name')"></i></th>
     <th ng-click="sortData('age')">Age <i ng- class="getSortClass('age')"></i></th>
     <th>....</th>
   </tr>
  </thead>
  <tbody>
    <tr ng-repeat="row in elem.data | orderBy:sortColumn:reverseSort">
     <td>...</td>
     ....
    </tr>
  </tbody>
</table>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.