Kendo Virtualization doesn't work as expected

2.2k views Asked by At

I'm trying to bind a list to my kendo combobox, the list contains more than 30000 records, so I need virtualization feature. I checked this documentation:

http://docs.telerik.com/kendo-ui/controls/editors/combobox/virtualization#valuemapper

and tried to implement it, but not luck.

My Web API

[Authorize]
    [HttpGet]
    [Route("app/clients")]
    [GzipCompressed]
    public IEnumerable<string> GetClients()
    {
        return businessLayer.GetClients();
    }

    [Authorize]
    [HttpGet]
    [Route("app/valuemapper")]
    [GzipCompressed]
    public int ValueMapper(string value)
    {
        if (string.IsNullOrWhiteSpace(value))
        {
            return -1;
        }
        var clients = businessLayer.GetClients(null);
        return clients.ToList().IndexOf(value);
    }

businessLayer.GetClients() will return all 30000+ records.

This is my js

$scope.clientsOptions = {     
        virtual: {
            itemHeight: 26,
            valueMapper: function(options) {
                $http({
                    url: config.endpoint + '/app' + '/valuemapper',
                    method: "GET",
                    params: {"value": options.value}
                }).then(function successResponse(response){
                  options.success(response.data);
                })
            }
        },
        height: 520,
        dataSource: getClientDataSource()
    }


function getClientDataSource() {
        var dataSource = new kendo.data.DataSource({
            transport: {
                read: function(options) {
                    $http({
                        method: 'GET',
                        url: config.endpoint + '/app' + '/clients',
                        headers: {
                            'Content-Type': "application/json",
                        }
                    }).then(function successResponse(response) {
                        options.success(response.data);
                    });
                }
            },
            pageSize: 80,
            serverPaging: true,
            serverFiltering: true
        });
        return dataSource;
    }

The problem about this code above: 1. The paging seems not work, when I serach a string in ComboBox, and select it, next time when I click array to open the combobox, it will call service again to fetch all of the data; 2. Mouse click can't select a selection, just keyboard works;

Anybody can help?

1

There are 1 answers

2
layonez On BEST ANSWER

Update

Your get clients method not apply paging to retrieved source

How it should look like:

[Authorize]
[HttpGet]
[Route("app/clients")]
[GzipCompressed]
public ActionResult GetClients([[DataSourceRequest] DataSourceRequest request)
{
    return Json(businessLayer.GetClients().ToDataSourceResult(request));
}

The send request is converted to DataSourceRequest, which holds the information about the server paging, filtering, sorting and etc. Then this information is passed to the ToDataSourceResult method, which builds the correct LINQ expression and retrieves the proper data chunk.

The idea of valueMapper is to retrieve the row index that matches particular value.


Im pretty sure that you should send converted values to your server in valueMapper

$scope.clientsOptions = {     
        virtual: {
            itemHeight: 26,
            valueMapper: function(options) {
                $http({
                    url: config.endpoint + '/app' + '/valuemapper',
                    method: "GET",
                    //here we convert values before sending 
                    params: convertValues(options.value)
                }).then(function successResponse(response){
                  options.success(response.data);
                })
            }
        },
        height: 520,
        dataSource: getClientDataSource()
    }

function convertValues(value) {
        var data = {};

        value = $.isArray(value) ? value : [value];

        for (var idx = 0; idx < value.length; idx++) {
                    data["values[" + idx + "]"] = value[idx];
        }

        return data;
}

And here ValueMapper server side example from kendo examples github https://github.com/telerik/kendo-ui-demos-service/blob/master/KendoCRUDService/Controllers/OrdersController.cs

public ActionResult ValueMapper(int[] values)
        {
            var indices = new List<int>();

            if (values != null && values.Any())
            {
                var index = 0;
                foreach (var order in OrderRepository.All()) 
                {
                    if (values.Contains(order.OrderID))
                    {
                        indices.Add(index);
                    }

                    index += 1;
                }
            }

            return this.Jsonp(indices);
        }

Check out that example from kendo docs

https://demos.telerik.com/kendo-ui/combobox/virtualization