Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AngularJS Directive for table header

I am trying to write a directive to deal with changing an icon class for table headers. What I would like is (what I believe anyway) the standard way of dealing with sorting by table headers. The directive would add a link element and upon a user's click sort by desc and change the icon to desc, upon click again sort by asc and once again the the icon. Here is what I have so far, but I am now at a loss for how to deal with the icon class as well as resetting other elements on the same table but outside of the directive's scope. Any help would be great!

angular.directive("tableHeaders", function() {
return {
    restrict: 'E',
    scope: {},
    template:'<i class="glyphicon glyphicon-filter"></i>',
    link: function(scope, element, attrs) {
        attrs.class = 'glyphicon glyphicon-sort-by-alphabet-alt';
    }
}
});

Here is what I have for the html side:

<th>First Name<a ng-click="newOrderBy('_firstName')"><table-headers></table-headers></a></th>
<th>Last Name<a ng-click="newOrderBy('_lastName')"><table-headers></table-headers></a></th>
<tr ng-repeat="item in items | orderBy:orderBy:reverse>
<td>{{item._firstName}}</td>
<td>{{item._lastName}}</td>
</tr>

The order by is currently handled in the controller:

   $scope.newOrderBy = function(order) {
        $scope.orderBy = order;
        $scope.reverse = !$scope.reverse;
    };
like image 412
Brian Avatar asked Sep 11 '13 01:09

Brian


2 Answers

What you need to do is for each element using your directive providing both an order and the current order (the one from your controller).

BTW I think your directive will be a better match as an attribute and not a tag. You can check the following code :

angular.module('myApp', []).directive("sort", function() {
return {
    restrict: 'A',
    transclude: true,
    template : 
      '<a ng-click="onClick()">'+
        '<span ng-transclude></span>'+ 
        '<i class="glyphicon" ng-class="{\'glyphicon-sort-by-alphabet\' : order === by && !reverse,  \'glyphicon-sort-by-alphabet-alt\' : order===by && reverse}"></i>'+
      '</a>',
    scope: {
      order: '=',
      by: '=',
      reverse : '='
    },
    link: function(scope, element, attrs) {
      scope.onClick = function () {
        if( scope.order === scope.by ) {
           scope.reverse = !scope.reverse 
        } else {
          scope.by = scope.order ;
          scope.reverse = false; 
        }
      }
    }
}
});

And the plunker that goes with it : http://plnkr.co/edit/P4cAm2AUGG36nejSjOpY?p=preview

The directive is used as such :

<thead>
  <tr>
    <th sort by="order" reverse="reverse" order="'name'">Name</th>
    <th>Phone</th>
    <th sort by="order" reverse="reverse" order="'age'">Age</th>        
  </tr>
</thead>
like image 184
Nicolas ABRIC Avatar answered Nov 16 '22 02:11

Nicolas ABRIC


Unless you are intent on writing your own directive, you might consider looking at what is available. ngmodules.org shows some directives that are already set up for table headers.

Here are a couple options with some sample code to give you a feel for both. They both look to be developed and very customizable.

ngTable

ngTable snapshot

angular.module('main', ['ngTable'])
.controller('DemoCtrl', function($scope, $filter, ngTableParams) {
    var data = [{name: "Moroni", age: 50}, ... ]

    $scope.tableParams = new ngTableParams({
        page: 1,            // show first page
        count: 10,          // count per page
        sorting: {
            name: 'asc'     // initial sorting
        }
    }, {
        total: data.length, // length of data
        getData: function($defer, params) {
            // use build-in angular filter
            var orderedData = params.sorting() ?
                                $filter('orderBy')(data, params.orderBy()) :
                                data;

            $defer.resolve(orderedData.slice((params.page() - 1) * params.count(), params.page() * params.count()));
        }
    });
});

UI Grid

UI Grid snapshot

angular.module('app', ['ngAnimate', 'ui.grid'])
.controller('MainCtrl', function ($scope) {
  $scope.gridOptions1 = {
    enableSorting: true,
    columnDefs: [
      { field: 'name' },
      { field: 'gender' },
      { field: 'company', enableSorting: false }
    ],
    onRegisterApi: function (gridApi) {
      $scope.grid1Api = gridApi;
    }
  };
});
like image 29
bholben Avatar answered Nov 16 '22 04:11

bholben