Search code examples
angularjsangularjs-ng-repeathtml-table

AngularJS sorting rows by table header


I have four table headers:

$scope.headers = ["Header1", "Header2", "Header3", "Header4"];

And I want to be able to sort my table by clicking on the header.

So if my table looks like this

H1 | H2 | H3 | H4
A    H    D   etc....
B    G    C
C    F    B
D    E    A

and I click on

H2

my table now looks like this:

H1 | H2 | H3 | H4
D    E    A   etc....
C    F    B
B    G    C
A    H    D

That is, the content of each column never changes, but by clicking on the header I want to order the columns by, the rows will reorder themselves.

The content of my table is created by a database call done with Mojolicious and is returned to the browser with

$scope.results = angular.fromJson(data); // This works for me so far

The rest of the code I have cobbled together looks something like this:

<table class= "table table-striped table-hover">
    <th ng-repeat= "header in headers">
        <a> {{headers[$index]}} </a>
    </th>
    <tr ng-repeat "result in results">
        <td> {{results.h1}} </td>
        <td> {{results.h2}} </td>
        <td> {{results.h3}} </td>
        <td> {{results.h4}} </td>
    </tr>
</table>

How do I order the columns from this point, just by clicking on the header at the top of the table?


Solution

  • I think this working CodePen example that I created will show you exactly how to do what you want.

    The template:

    <section ng-app="app" ng-controller="MainCtrl">
      <span class="label">Ordered By: {{orderByField}}, Reverse Sort: {{reverseSort}}</span><br><br>
      <table class="table table-bordered">
        <thead>
          <tr>
            <th>
              <a href="#" ng-click="orderByField='firstName'; reverseSort = !reverseSort">
              First Name <span ng-show="orderByField == 'firstName'"><span ng-show="!reverseSort">^</span><span ng-show="reverseSort">v</span></span>
              </a>
            </th>
            <th>
              <a href="#" ng-click="orderByField='lastName'; reverseSort = !reverseSort">
                Last Name <span ng-show="orderByField == 'lastName'"><span ng-show="!reverseSort">^</span><span ng-show="reverseSort">v</span></span>
              </a>
            </th>
            <th>
              <a href="#" ng-click="orderByField='age'; reverseSort = !reverseSort">
              Age <span ng-show="orderByField == 'age'"><span ng-show="!reverseSort">^</span><span ng-show="reverseSort">v</span></span>
              </a>
            </th>
          </tr>
        </thead>
        <tbody>
          <tr ng-repeat="emp in data.employees|orderBy:orderByField:reverseSort">
            <td>{{emp.firstName}}</td>
            <td>{{emp.lastName}}</td>
            <td>{{emp.age}}</td>
          </tr>
        </tbody>
      </table>
    </section>
    

    The JavaScript code:

    var app = angular.module('app', []);
    
    app.controller('MainCtrl', function($scope) {
      $scope.orderByField = 'firstName';
      $scope.reverseSort = false;
    
      $scope.data = {
        employees: [{
          firstName: 'John',
          lastName: 'Doe',
          age: 30
        },{
          firstName: 'Frank',
          lastName: 'Burns',
          age: 54
        },{
          firstName: 'Sue',
          lastName: 'Banter',
          age: 21
        }]
      };
    });