Server-side paging+filtering+sorting for ng-grid with WebAPI Server-side paging+filtering+sorting for ng-grid with WebAPI angularjs angularjs

Server-side paging+filtering+sorting for ng-grid with WebAPI


After experimenting a bit, I think I found the correct code. This post about $apply helped me a bit: http://jimhoskins.com/2012/12/17/angularjs-and-apply.html. In fact, if I understand well the call to apply should not be needed at all, given that my data are coming from $http which already provides this. So, I ended with just setting the scope items variable in the success callback. Here is the full JS again, hope this can help some newcomer like me. Now I'm going to expand the test with TypeScript models, services and all the real-world stuff: I fear I'll have to make some new post... :)

var app = angular.module('MyApp', ['ngGrid']);app.controller('MainController', ['$scope', '$http', function ($scope, $http, $apply) {    $scope.items = [];    // filter    $scope.filterOptions = {        filterText: "",        useExternalFilter: true    };    // paging    $scope.totalServerItems = 0;    $scope.pagingOptions = {        pageSizes: [25, 50, 100],        pageSize: 25,        currentPage: 1    };    // sort    $scope.sortOptions = {        fields: ["name"],        directions: ["ASC"]    };    // grid    $scope.gridOptions = {        data: "items",        columnDefs: [            { field: "id", displayName: "ID", width: "60" },            { field: "name", displayName: "Name", pinnable: true },            { field: "age", displayName: "Age", width: "60" },            { field: "isFemale", displayName: "F", width: "40" }        ],        enablePaging: true,        enablePinning: true,        pagingOptions: $scope.pagingOptions,                filterOptions: $scope.filterOptions,        keepLastSelected: true,        multiSelect: false,        showColumnMenu: true,        showFilter: true,        showGroupPanel: true,        showFooter: true,        sortInfo: $scope.sortOptions,        totalServerItems: "totalServerItems",        useExternalSorting: true,        i18n: "en"    };    $scope.refresh = function() {        setTimeout(function () {            var sb = [];            for (var i = 0; i < $scope.sortOptions.fields.length; i++) {                sb.push($scope.sortOptions.directions[i] === "DESC" ? "-" : "+");                sb.push($scope.sortOptions.fields[i]);            }            var p = {                name: $scope.filterOptions.filterText,                pageNumber: $scope.pagingOptions.currentPage,                pageSize: $scope.pagingOptions.pageSize,                sortInfo: sb.join("")            };            $http({                url: "/api/item",                method: "GET",                params: p            }).success(function(data, status, headers, config) {                $scope.totalServerItems = data.totalItems;                $scope.items = data.items;            }).error(function(data, status, headers, config) {                alert(JSON.stringify(data));            });        }, 100);    };    // watches    $scope.$watch('pagingOptions', function (newVal, oldVal) {        if (newVal !== oldVal) {            $scope.refresh();        }    }, true);    $scope.$watch('filterOptions', function (newVal, oldVal) {        if (newVal !== oldVal) {            $scope.refresh();        }    }, true);    $scope.$watch('sortOptions', function (newVal, oldVal) {        if (newVal !== oldVal) {            $scope.refresh();        }    }, true);    $scope.refresh();}]);

(As a sidenote, you can see from the code that I'm passing a single string for sort data, rather than two arrays for fields and directions. In fact, I could not find the right way of receiving arrays as members of my input model in the C# controller; so I'm just passing a single string where each field name is prefixed by + or - according to the ascending/descending direction).


You are setting datasource on ng-grid to items but then you are never updating the items array on server success callback.

On succcess callback do something like this

$scope.totalServerItems = data.totalItems;angular.forEach(data.items, function(item) {   $scope.items.push(item);});


It might help too

The HTML code-sample

<html ng-app="myApp">      <head lang="en">        <meta charset="utf-8">        <title>Getting Started With ngGrid code-sample</title>          <script type="text/javascript" src="angular.js"></script>        <script type="text/javascript" src="ng-grid-1.3.2.js"></script>    </head>    <body ng-controller="MyCtrl">        <div class="gridStyle" ng-grid="gridOptions"></div>    </body></html>

The AngulaJs code-sample

var app = angular.module('myApp', ['ngGrid']);app.controller('MyCtrl', function($scope, $http) {    $scope.filterOptions = {        filterText: "",        useExternalFilter: true    };     $scope.totalServerItems = 0;    $scope.pagingOptions = {        pageSizes: [250, 500, 1000],        pageSize: 250,        currentPage: 1    };      $scope.setPagingData = function(data, page, pageSize){          var pagedData = data.slice((page - 1) * pageSize, page * pageSize);        $scope.myData = pagedData;        $scope.totalServerItems = data.length;        if (!$scope.$$phase) {            $scope.$apply();        }    };    $scope.getPagedDataAsync = function (pageSize, page, searchText) {        setTimeout(function () {            var data;            if (searchText) {                var ft = searchText.toLowerCase();                $http.get('jsonFiles/largeLoad.json').success(function (largeLoad) {                            data = largeLoad.filter(function(item) {                        return JSON.stringify(item).toLowerCase().indexOf(ft) != -1;                    });                    $scope.setPagingData(data,page,pageSize);                });                        } else {                $http.get('jsonFiles/largeLoad.json').success(function (largeLoad) {                    $scope.setPagingData(largeLoad,page,pageSize);                });            }        }, 100);    };    $scope.getPagedDataAsync($scope.pagingOptions.pageSize, $scope.pagingOptions.currentPage);    $scope.$watch('pagingOptions', function (newVal, oldVal) {        if (newVal !== oldVal && newVal.currentPage !== oldVal.currentPage) {          $scope.getPagedDataAsync($scope.pagingOptions.pageSize, $scope.pagingOptions.currentPage, $scope.filterOptions.filterText);        }    }, true);    $scope.$watch('filterOptions', function (newVal, oldVal) {        if (newVal !== oldVal) {          $scope.getPagedDataAsync($scope.pagingOptions.pageSize, $scope.pagingOptions.currentPage, $scope.filterOptions.filterText);        }    }, true);    $scope.gridOptions = {        data: 'myData',        enablePaging: true,        showFooter: true,        totalServerItems: 'totalServerItems',        pagingOptions: $scope.pagingOptions,        filterOptions: $scope.filterOptions    };});