NibblyPig
NibblyPig

Reputation: 52952

Returning metadata from .Read() and using it in a kendo grid

I'm using a grid with asp.net MVC. Currently the grid is using .DataSource(c => c.Read()) to call a URL that returns an IEnumerable<item> which goes into the grid.

I want to implement paging in the grid. However the data does not have the normal method of paging (count, page number etc.).

Instead when I retrieve my data internally I get the data back like this:

{ items: [. . . ], nextPage: 'J23jeg9e93', previousPage: 'oqow0r93285' }

To get the next page you must make the request again for the data, but include the paging token for next or previous page.

At the moment I am only returning the items array to the grid, so no nextPage/previousPage metadata.

I can't see any way to include this metadata, as I am simply returning an IEnumerable of items so there is no wrapper object to put the metadata in.

I can use .Data() to attach metadata to the read request, but I need to do it the other way around. Once I get the metadata back I need to be able to store it in a javascript variable so that I can send it in .Data()

Upvotes: 0

Views: 1009

Answers (1)

The Dread Pirate Stephen
The Dread Pirate Stephen

Reputation: 3169

I don't know how you are actually triggering the NextPage, PreviousPage operations, but...

You can use the MVC Custom DataSource configuration to provide access to more options like the Schema configuration. http://docs.telerik.com/aspnet-mvc/getting-started/custom-datasource

The Schema configuration allows you to add a Parse function that can take your custom result format:

{ items: [. . . ], nextPage: 'J23jeg9e93', previousPage: 'oqow0r93285' }

and extract the items(to give to the grid) AND the nextPage, previousPage values(for you to store to pass to the next read request).

For example:

Sample Grid:

@(Html.Kendo().Grid<TelerikMvcApp4.Models.GridViewModel>()
.Name("grid")
.DataSource(ds => ds
    .Custom()
    .Batch(true)
    .Schema(schema => schema
        .Parse(@<text>parseData</text>)
    )
    .Transport(transport => transport
        .Read(read => read.Action("Grid_Read", "Home").Type(HttpVerbs.Post).Data("readData"))
    )
    .PageSize(1)
    .ServerPaging(true)
)
.Pageable()
)

Sample parseData and readData javascript:

<script>
var nextPage,
    previousPage;
function readData() {
    // Return the "extra" data that should be posted with each grid read request, which is the nextPage/previousPage we were given in the previous request respsonse.
    return {
        nextPage: nextPage,
        previousPage: previousPage
    };
}
function parseData(data) {
    // Parse the response from the server as it isn't in the typical format expected by the grid.

    // Extract your nextPage/previousPage, store it somewhere so they can be added to the next grid request.
    nextPage = data.nextPage;
    previousPage = data.previousPage;

    // Return the actual data that should be displayed in the grid.
    return data.items;
}
</script>

Sample grid read action:

[HttpPost]
    public ActionResult Grid_Read([DataSourceRequest] DataSourceRequest request, string nextPage, string previousPage)
    {

        // "Fetch" the data, presumably doing something with nextPage and previousPage...
        var items = new List<GridViewModel>()
        {
            new GridViewModel() { name = "bob", age = 23},
            new GridViewModel() { name = "jim", age = 43},
        };
        // Determine what the new nextPage, previousPage should be...
        var newNextPage = "J23jeg9e93";
        var newPreviousPage = "oqow0r93285";

        return Json(new
        {
            items = items,
            nextPage = newNextPage,
            previousPage = newPreviousPage
        });
    }

This is not a complete, robust solution, but I think it can be made workable and will at least point you in a possible direction.

Upvotes: 1

Related Questions