3
votes

I have a kendo grid, and when an item is selected I want to modify the underlying dataitem so i'm doing this ...

selectionChange: function(e)
    {
        var component = $(this.table).closest('.component');
        var grid = this;
        var val = !component.hasClass("secondary");

        var selection = grid.dataItems(grid.select());
        selection.forEach(function () {
            this.set("SaleSelected", val);
        });
    }

I also have 2 buttons that allow me to push items between the 2 grids which do this ...

select: function (e) {
            e.preventDefault();
            var sender = this;

            // get kendo data source for the primary grid
            var source = $(sender).closest(".component")
                .find(".component.primary")
                .find(".details > [data-role=grid]")
                .data("kendoGrid")
                .dataSource;

            // sync and reload the primary grid
            source.sync()
                .done(function () {
                    source.read();
                    my.Invoice.reloadGridData($(sender).closest(".component").find(".component.secondary").find(".details > [data-role=grid]"));
                });

            return false;
        },
        deselect: function (e) {
            e.preventDefault();
            var sender = this;
            debugger;
            // get kendo data source for the secondary grid
            var source = $(sender).closest(".component")
                .find(".component.secondary")
                .find(".details > [data-role=grid]")
                .data("kendoGrid")
                .dataSource;

            // sync and reload the primary grid
            source.sync()
                .done(function () {
                    source.read();
                    my.Invoice.reloadGridData($(sender).closest(".component").find(".component.primary").find(".details > [data-role=grid]"));
                });

            return false;
        }

Essentially the "selected items" from grid1 can be marked as such on the server then the grids get reloaded to move the items over.

All good I thought, but apparently Kendo has other ideas.

Editing a data item causes its owning grid to rebind losing the selection state resulting in some confusing behaviour for the user.

Is there a way to tell kendo "i'm going to edit this unbound property right now, don't go messing with binding"?

2

2 Answers

2
votes

Ok it turns out kendo is a bit of a wierdo and I still have no idea why they insist you call all their "api stuff" to do simple tasks when doing things more directly actually works better.

In my case I removed the selection change call altogether and let kendo handle that, then in my selection button handlers to move the data between grids I updated the properties directly on the data items instead of calling "item.set("prop", value)" i now have to do "item.prop = value".

The net result is this ...

select: function (e) {
            e.preventDefault();
            var sender = this;

            // get some useful bits
            var component = $(sender).closest(".component");
            var primaryGrid = component.find(".component.primary").find(".details > [data-role=grid]").data("kendoGrid");

            // get the new selection, and mark the items with val
            var selection = $(primaryGrid.tbody).find('tr.k-state-selected');

            selection.each(function (i, row) {
                primaryGrid.dataItem(row).SaleSelected = true;
                primaryGrid.dataItem(row).dirty = true;
            });

            // sync and reload the primary grid
            primaryGrid.dataSource.sync()
                .done(function () {
                    primaryGrid.dataSource.read();
                    component.find(".component.secondary")
                        .find(".details > [data-role=grid]")
                        .data("kendoGrid")
                        .dataSource
                        .read();
                });

            return false;
        },
        deselect: function (e) {
            e.preventDefault();
            var sender = this;

            // get some useful bits
            var component = $(sender).closest(".component");
            var secondaryGrid = component.find(".component.secondary").find(".details > [data-role=grid]").data("kendoGrid");

            // get the new selection, and mark the items with val
            var selection = $(secondaryGrid.tbody).find('tr.k-state-selected');

            selection.each(function (i, row) {
                secondaryGrid.dataItem(row).SaleSelected = false;
                secondaryGrid.dataItem(row).dirty = true;
            });

            // sync and reload the primary grid
            secondaryGrid.dataSource.sync()
                .done(function () {
                    secondaryGrid.dataSource.read();
                    component.find(".component.primary")
                        .find(".details > [data-role=grid]")
                        .data("kendoGrid")
                        .dataSource
                        .read();
                });

            return false;
        }

kendo appears to be taking any call to item.set(p, v) as a trigger to reload data so avoiding the kendo wrapper and going directly to the item properties allows me direct control of the process.

Moving the code from the selection change event handler to the button click handler also means i only care about that data being right when it actually needs to be sent to the server, something I just need to be aware of.

I don't like this, but it's reasonably clean and the ui shows the right picture even if the underlying data isn't quite right.

My other option would be to create a custom binding but given that the binding would have to result in different results depending on weather it was binding to the primary or the secondary grid I suspect that would be a lot of js code, this feels like the lesser of 2 evils.

0
votes

I think you can bind the dataBinding event to just a "preventDefault" and then unbind it and refresh at your leisure

var g = $("#myGrid").data("kendoGrid");

g.bind("dataBinding", function(e) { e.preventDefault(); });

then later...

g.unbind("dataBinding");