Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular-Kendo grid - server side pagination

I need to implement server side pagination in Angular-Kendo grid. I couldn't get a clear understanding on how to do that from Angular side.

Could anyone please help?

like image 855
JPN Avatar asked Oct 31 '13 15:10

JPN


People also ask

What is Pageable in kendo grid?

kendo:grid-pageable-messagesThe text messages displayed in pager. Use this option to customize or localize the pager messages.

How do I change the page size in kendo grid?

Solution. Calculate the number of rows that will fit in the available space by subscribing to the resize event of the window element. Change the pageSize by using the pageSize method of the dataSource.

How do I get the current page number in kendo grid?

You can get page number by calling function page() on the dataSource object in kendo grid you have, and page size by calling function pageSize() of that object.


2 Answers

With the newest version of Kendo UI out (in Beta right now) there is another way we can implement server side paging, using the $http.post method Angular provides with the Kendo Grid read function.

This is an example using a MVC 5 controller as your endpoint for the data you get from the data source. It simulates server paging by sending the page and pageSize to the controller, you could also send the take and skip if needed and handle it however you like.

HTML Markup

<div ng-controller="MyCtrl">
    <kendo-grid k-options="mainGridOptions"></kendo-grid>
</div>

JavaScript

function MyCtrl($scope, $http) {
    $scope.mainGridOptions = {
        dataSource: {
            schema: {
                data: "Data",
                total: "Total"
            },
            transport: {
                read: function (e) {//You can get the current page, pageSize etc off `e`.
                    var requestData = {
                        page: e.data.page,
                        pageSize: e.data.pageSize,
                        type: "hello"
                    };
                    console.log(e);
                    $http({ method: 'POST', url: 'Home/DataSourceResult', data: requestData }).
                    success(function (data, status, headers, config) {
                        e.success(data);
                        //console.log(data.Data);
                    }).
                    error(function (data, status, headers, config) {
                        alert('something went wrong');
                        console.log(status);
                    });
                }
            },
            pageSize: 1,
            serverPaging: true,
            serverSorting: true
        },
        selectable: "row",
        pageable: true,
        sortable: true,
        groupable: true
    }
}

You can get the current pageSize, page, take, skip and a lot more off of the argument e in the read: function(e){} declaration.

Because the post values reference the arguments from the read function, they update every time the page is updated on the grid. This is what you can use to update your post values every time the grid makes a change. The grid then re-binds itself.

Home/DataSourceResult Controller

[HttpPost]
    public ActionResult DataSourceResult(int page, string type, int pageSize)
    {
        ResponseData resultData = new ResponseData();
        string tempData = "";
        if (page == 1)
        {
            tempData = "[{\"NAME\": \"Example Name 1\", \"DESCRIPTION\": \"Example Description 1\"},{\"NAME\": \"Example Name 2\",\"DESCRIPTION\": null}]";
        }
        else if (page == 2)
        {
            tempData = "[{\"NAME\": \"Example Name 3\", \"DESCRIPTION\": \"Example Description 3\"},{\"NAME\": \"Example Name 4\",\"DESCRIPTION\": \"Example Description 4\"}]";
        }
        resultData.Data = tempData;
        resultData.Total = "4";
        string json = JsonConvert.SerializeObject(resultData);
        json = json.Replace(@"\", "");
        json = json.Replace("\"[{", "[{");
        json = json.Replace("}]\"", "}]");
        return Content(json, "application/json");
    }

Very basic, but exactly what I needed, and may help you as well. This uses the native Angular http.get functionality while still allowing the Kendo Grid to do most of your heavy lifting.

like image 93
Blunderfest Avatar answered Oct 19 '22 22:10

Blunderfest


The Kendo grid intrinsically supports server side paging, at least it has a handy built in API to help out there, so you just need to hook all the pieces together. Here's what I came up with, my grid's datasource:

$scope.myGrid.dataSource = new kendo.data.DataSource({
    transport:{
               read:{
                      url: '/api/mygridapi?orderId=113',
                      dataType: 'json'
               }
            },
    pageSize: 5,
    serverPaging: true,
    serverSorting: true,
    serverFiltering: true,
    serverGrouping: true,
    serverAggregates: true,
    schema:{
            total: function(response) {
                    return 13; // call some function, or some scope variable that know the total items count
                },
                model: {
                    id: "id",
                    fields: {
                        'id': { type: "number", editable: false },
                        'name': { type: "string", editable: true, nullable: false, validation: { required: true } },
                        'price': { type: "number", editable: true, nullable: false, validation: { required: true } },
                    }
                }
            }
        });

and my grid markup:

<div kendo-grid k-pageable='{ "pageSize": 5, "refresh": true, "pageSizes": false }'
     k-height="'250px'" k-column-menu="false" k-filterable="true" k-sortable="true" k-groupable="true"
     k-data-source="myGrid.dataSource" k-options="{{myGrid.gridOpts}}" k-on-change="onSelectHandler(kendoEvent)">

and my web api controller:

[System.Web.Http.HttpGet]
public IEnumerable<ProductsDTO> Get(int orderId)
{
     NameValueCollection nvc = HttpUtility.ParseQueryString(Request.RequestUri.Query);
          //the name value captures the paging info that kendo automatically appends to the query string when it requests data
              //it has info such as teh current page, page size etc....
     int take = int.Parse(nvc["take"]);
     int skip = int.Parse(nvc["skip"]);

     return productsSvc.GetProductsOfOrder(orderId,skip,take);
}

My service returns an IQueryable, but it could also return a concrete list as returning an IQueryable did nothing in helping Kendo figure out how many total items there were. The main issue for me was that the grid was not realising the total items count correctly, for example the first page would be displayed (first 5 items) however the remaining items weren't noticed and as a result the grids paging buttons were disabled so I kinda hacked around that but manually setting the total number of items, that was these lines of code:

schema:{
        total: function(response) {
                return 13; // call some function, or some scope variable that know the total items count
        },.........

One thing bothering me is having to set the total items count manually. Worth mentioning that when setting up the datasource you can pass in a function to the read property of the transport object, that function will have as a parameter an object containing the current paging/filtering info, so you could use that to build a query string manually rather than relying on the default kendo server request:

transport: {
           read: function (options) {
                 console.log(options);//see whats inside
                 //we can use the pageNo and pageSize property to create a query string manually
           }
}
like image 39
Mohammad Sepahvand Avatar answered Oct 19 '22 23:10

Mohammad Sepahvand