Question

I am building a website using MVC 4, Web API, and Kendo UI controls.

On my page I am using a Kendo UI Listview to filter my grid. I'm trying to add an "ALL" option as the first item in my listview.

Here is the listview:

var jobsfilter = $("#jobfilter").kendoListView({
            selectable: "single",
            loadOnDemand: false,
            template: "<div class='pointercursor' id=${FilterId}>${FilterName}</div>",
            dataSource: filterDataSource,
            change: function (e) {
                var itm = this.select().index(), dataItem = this.dataSource.view()[itm];
                if (dataItem.FilterId !== 0) {
                    var $filter = new Array();
                    $filter.push({ field: "JobStatusId", operator: "eq", value: dataItem.FilterId });
                    jgrid.dataSource.filter($filter);
                } else {
                    jgrid.dataSource.filter({});
                }
            }
        });

Here is my datasource:

 var filterDataSource = new kendo.data.DataSource({
            transport: {
                read: {
                    url: "api/Filter"
                }
            },
            schema: {
                model: { id: "FilterId" }
            }
        });

I have tried a few different methods to make this happen:

  • I can make it work if I attach it to a button - but I need it there when the data loads.
  • If I add it to the dataBound event of the listview, it causes the databound event to go into a loop and adds the item a bunch (IE) or kills the browser (firefox). Adding preventDefault did nothing.
  • I've read up on adding a function to the Read paramter of the datasource, but I think that is simply not the correct place to do it.

Based on what I've read, I think that I should be able to do it in the dataBound event of the listview and that my implementation is incorrect. Here is the listview with dataBound event added that crashes my browser (Firefox) - or adds about 50 "All" items to the listview (IE).

var jobsfilter = $("#jobfilter").kendoListView({
            selectable: "single",
            loadOnDemand: false,
            template: "<div class='pointercursor' id=${FilterId}>${FilterName}</div>",
            dataSource: {
                transport: {
                    read: {
                        url: "api/Filter"
                    }
                }
            },
            dataBound: function (e) {
                var dsource = $("#jobfilter").data("kendoListView").dataSource;
                dsource.insert(0, { FilterId: 0, FilterName: "All" });
                e.preventDefault();
            },
            change: function (e) {
                var itm = this.select().index(), dataItem = this.dataSource.view()[itm];
                if (dataItem.FilterId !== 0) {
                    var $filter = new Array();
                    $filter.push({ field: "JobStatusId", operator: "eq", value: dataItem.FilterId });
                    jgrid.dataSource.filter($filter);
                } else {
                    jgrid.dataSource.filter({});
                }
            }
        });

Any help would be greatly appreciated.

Was it helpful?

Solution

Why don't you add it server-side? Anyway, if you want to do it in dataBound, just check whether it exists and only add if it doesn't:

dataBound: function (e) {
    var dsource = this.dataSource;
    if (dsource.at(0).FilterName !== "All") {
        dsource.insert(0, {
            FilterId: 0,
            FilterName: "All"
        });
    }
},

As an explanation to the problem you're seeing: you're creating an infinite loop since inserting an element in the data source will trigger the change event and the list view will refresh and bind again (and thus trigger dataBound).

You could also encapsulate this in a custom widget:

(function ($, kendo) {
    var ui = kendo.ui,
        ListView = ui.ListView;

    var CustomListView = ListView.extend({
        init: function (element, options) {
            // base call to widget initialization
            ListView.fn.init.call(this, element, options);

            this.dataSource.insert(0, {
                FilterId: 0,
                FilterName: "All"
            });
        },

        options: {
            name: "CustomListView"
        }
    });

    ui.plugin(CustomListView);
})(window.jQuery, window.kendo);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top