Presetting kendo DataSource PageSize to “All”

2019-08-03 04:07发布

问题:

Whenever a user changes the pagination on a grid, I save the setting in localStorage and retrieve it to set it back whenever the user navigates again to the page. To retrieve it I am using the pageSize property of the dataSource where I pass an IIF like so:

    pageSize: function () {
        var pageSize = 10;
        if (window.localStorage) {
            var userPreferencePageSize = localStorage.getItem("somegridPageSize");
            if (userPreferencePageSize === parseInt(userPreferencePageSize)) {
                userPreferencePageSize = parseInt(userPreferencePageSize);
            }

            if (!isNaN(userPreferencePageSize)) {
                pageSize = userPreferencePageSize;
            }
        }
        return pageSize;
    }()

This worked well but a requirement appeared for the user to be able to set the pageSize to "All". Kendo handles "All" in the Grid so I thought this will let me set the dataSource pageSize to the string "All" (pageSize="All") as well. When I do it however the grid starts displaying NaN of X records and displays an empty grid. So the question is.. how do I preset the pageSize of the dataSource to just "All"?

NOTE: An alternative is to just fetch the grid maximum total count and then replace the number displayed in the dropdown with jquery text("All) but that looks like a hack and it seems to me this should already be inbuilt into the framework but I can't find anything in the doc's.

EDIT: This is getting even funnier. Due to lack of other options I implemented it like in the note and just set the dataSource pageSize directly:

$("#Grid").data("kendoGrid").dataSource.pageSize(pageSize);

But this is causing the filters on grid to malfunction and throw "string is not in correct format" (misleading error) error from the endpoint. After enough research I found out its caused by the DataSourceRequest doing some unidentifiable shuru buru in the background. Since setting the dataSource pageSize causes issues, I tried just setting the dropdown programatically and let kendo trigger the request to update pageSize itself like so:

            var selectBox = $(".k-pager-sizes").find("select");
            selectBox.val(pageSize);
            selectBox.find("option[value='" + pageSize + "']").prop('selected', true);

But the grid doesn't let me do it and keeps reverting any changes I do inside the DOM from javascript.

So the question is, how in earth can you change the pageSize of a server-side kendo grid from javascript (triggering an extra request to endpoint).

回答1:

To answer the question. This appears to be a bug in Kendo. Setting the pageSize to 0 (shortcut for "all") after the dataSource was already bound will always result in the grid having issues with any custom filters declared inside of a toolbar template.

To be exact, if you have a custom filter defined inside of the toolbar template:

@(Html.Kendo().TextBox().Name("Filter").Deferred())

You wire it up through the dataSource definition on the grid like:

.DataSource(ds =>
    ds.Ajax()
        .PageSize(defaultPageSize)
        .Read(a => a.Action(actionName, controllerName, new
        {
            param = Model.param
        }).Data("getFilterParameters")))

in javaScript fetching the parameters like:

getFilterParameters: function () {
    return this.filterParameters;
},

populating them with a method:

filter: function () {
    var grid = $("#Grid").data("kendoGrid");

    this.filterParameters = {
        param: $("#Filter").val()
    };

    grid.dataSource.page(1);
}

that has a simple event listener wired to it:

$("#Filter").on("keyup", filter);

Then after changing the pageSize programatically to 0/"all" with:

$("#Grid").data("kendoGrid").dataSource.pageSize(0);

The filter will start to always return NaN as the current page / skip of the filter object passed to the server with the query parameters (even though grid will display the numbers correctly). This will cause a "string is not in correct format" exception inside framework code on the endpoint whenever you try using the filter. A solution to the above is to slightly modify the getFilterParameters method:

    getFilterParameters: function (e) {
        // Workaround for Kendo NaN pager values if pageSize is set to All 
        if (isNaN(e.page)) e.page = 1;
        if (isNaN(e.skip)) e.skip = 0;
        //
        return this.filterParameters;
    }

This will re-initialize the page and skip values before submitting the filter request. These values will anyway be re-populated on the endpoint with the correct values. Wasn't me who noticed it but another developer working on the project, credit goes to her.