Last Updated: September 16, 2020
·
37.17K
· hin556

AngularJS table with paging, filter and sorting backed by Rails

Installing ng-table

ng-table is an AngularJS module enables HTML table with paging, filter and sorting functions.

Codes added for setting up ng-table

[bower.json] "ng-table": "0.3.1"
[app.js]      angular.module('myApp', ['ngTable']);
[index.html]  <script src="/bower_components/ng-table/ng-table.js"></script>

Declare an ng-table enabled HTML table

<table ng-table="usersTableParams" show-filter="true">
  <tbody>
    <tr ng-repeat="user in **$data**">
      <td data-title="'Name'" filter="{ 'full_name': 'text' }" sortable="'full_name'">
        {{user.full_name}}
      </td>
      <td data-title="'Email'" filter="{ 'email': 'text' }" sortable="'email'">
        {{user.email}}
      </td>
    </tr>
  </tbody>
</table>

Feed data from controller to the table

.controller('UsersTableCtrl',
 function ($scope, $log, ngTableParams, Users) {
   $scope.fetchUsers = function() {  
     if (!$scope.usersTableParams) {
       $scope.usersTableParams.reload();
       return;
     }

     $scope.usersTableParams = new ngTableParams({
       page: 1,
       count: count
     }, {
       total: 0,
       getData: function($defer, params) {
         // prepare options to be sent to Rails

         var queryOptions = {
           page: params.page(),
           page_size: params.count()
         }

         // params.filter() - array of key-value filters declared in view
         queryOptions.search = params.filter()

         // tableParams.orderBy() - an array of string indicating both the sorting column and direction (e.g. ["+name", "-email"])
         if (tableParams.sorting()) {
           // only interested in first sort column for now
           var orderBy = tableParams.orderBy()[0];

           queryOptions.order_by = orderBy.substring(1);
           queryOptions.order_dir = orderBy[0] == '+' ? 'asc' : 'desc'
         }

         // Users is a REST AngularJS service that talks to Rails and return promise
         Users.getAll(queryOptions).then(function(result) {
           params.total(result.meta.total);
           $defer.resolve(result.users);
           $scope.meta = result.meta;
           $log.debug('ok fetching users:', result.users);
         }, function(result) {
           $log.debug('error fetching users:', result);
         });
       }
     });
   }
 });

Rails handles users query with paginated result

Gem to do advance ActiveRecord query

gem install 'squeel'

squeel

Gem to do pagination

gem install 'will_paginate'

will_paginate

Codes added in UsersController

def index
  params.require(:page)
  params.require(:page_size)

  page = params[:page].to_i
  page_size = params[:page_size].to_i

  @users = User.all

  if params[:search]
    # credit by gem 'squeel'
    search_params = JSON.load(params[:search])
    @users = @users.where{full_name.like_any ["#{search_params['full_name']}%"]} if search_params["full_name"].present?
    @users = @users.where{email.like_any ["#{search_params['email']}%"]} if search_params["email"].present?
  end

  @users_count = @users.count

  # credit by gem 'will_paginate'
  @users = @users.paginate(:page => page, :per_page => page_size)

  if params[:order_by] && params[:order_dir]
    @users = @users.order("users.#{params[:order_by]} #{params[:order_dir]}")
  elsif params[:order_by]
    @users = @users.order("users.#{params[:order_by]} desc")
  else
    @users = @users.order(id: :desc)
  end

  render json: @users, root: :users, each_serializer: UserSerializer, meta: { total: @users_count }
end