6

I'm using SlickGrid with knockout.js based on the example http://jsfiddle.net/rniemeyer/A9NrP/

I have the grid populating and the add button working as per the example. The problem I'm having is when I update the rows property of my viewmodel via a ko.dependentObservable the 'update' section of the ko.bindingHandlers is fired but slick grid does not pick up the changes.

html that defines the binding:

<div id="grid" data-bind="slickGrid: { data: rows, columns: columns }"></div>

SlickGrid code (same as the example):

var grid;
ko.bindingHandlers.slickGrid = {
    init: function (element, valueAccessor) {
        var settings = valueAccessor();
        var data = ko.utils.unwrapObservable(settings.data);
        var columns = ko.utils.unwrapObservable(settings.columns);
        var options = ko.utils.unwrapObservable(settings.options) || {};
        grid = new Slick.Grid(element, data, columns, options);
    },
    update: function (element, valueAccessor, allBindingAccessor, viewModel) {
        var settings = valueAccessor();
        // I can see the correct data here but the grid does not update
        var data = ko.utils.unwrapObservable(settings.data);  
        grid.render();
    }
}

my model:

myViewModel = {
data : ko.observableArray(),
tabs: ['High', 'Medium', 'Low'],
rows : ko.observableArray([]),
columns : [
        {
            id: "id",
            name: "ID",
            field: "id"
        },
        {
            id: "Location",
            name: "Location",
            field: "Location"
        },
        {
            id: "Comment",
            name: "Comment",
            field: "Comment"
        }
        ],
addItem: function() { // this works and SlickGrid adds a new row
  this.rows.push(new ModelRow(0, "New", 5.00));  
},

}

The code that make the ajax call, and fires ko.bindingHandlers.slickGrid.update but slickgrid doesnt seem to pick up the changes, the ajax does return valid data, and is fired when the user clicks on a link:

ko.dependentObservable(function () {
   if (this.data.lastAlarmRequest) this.data.lastAlarmRequest.abort();
       this.data.lastAlarmRequest = $.get("/audit/alarmsdata/high", null, this.rows);
}, i2owater.viewmodels.AlarmsForViewModel);

Why does the addItem function work but not the ko.bindingHandlers.slickGrid.update? In the update function I can see the correct data that the grid should be bound to. Is it because all the data in the rows propertys is overwritten?

UPDATE: I've tried to use grid.invalidate(); but it doesnt work and have also seen that the addItem function stops working once ko.dependentObservable is executed

Dave
  • 3,812
  • 5
  • 31
  • 39
  • Did you ever solve this problem? I'm having the same issue – Danny Jones Oct 20 '11 at 11:24
  • Hi Danny, I'm afraid I haven't fixed it yet, I had to stop using the KO bindings and use jquery with SlickGrids dataView object, I do want to come back to this and getting working with KO. just cant say when I'll get around to it. Please let me know if you get any further than I did. – Dave Oct 20 '11 at 13:01

3 Answers3

3

I've updated rniemeyer's very useful jsfiddle to fix a scrollbar bug. In the original, try adding 20 rows then use the vertical scrollbar, and you'll see a UI problem. The issue is that the scrollpane incorrectly calculates the view size, so the scrollbar jitters.

Here an updated version.

EDIT: Knockout and slickgrid have been updated so I've updated the fiddle: EDIT: And again:

http://jsfiddle.net/5ddNM/79/

Note the following:

grid.resizeCanvas(); 
hlascelles
  • 1,061
  • 11
  • 15
2

I just had the same issue and have found the solution, change your update code to the following:

update: function (element, valueAccessor, allBindingAccessor, viewModel) {
        var settings = valueAccessor();
        // I can see the correct data here but the grid does not update
        var data = ko.utils.unwrapObservable(settings.data);  
        grid.setData(data,true)
        grid.render();
    }

By the way, the true parameter in setData indicates if you want the grid to scroll back to the top or not.

Danny Jones
  • 1,648
  • 1
  • 10
  • 10
1

In my case I needed to use slickgrid and knockout with another viewmodels binded to different controls. I used http://jsfiddle.net/hlascelles/5ddNM/ as example and fixed few things there. Use http://jsfiddle.net/Schnapz/z4YLD/2/ or look description below.

Declaration of grid, Item and viewModel you can leave as written in example. But, binding should be common for all models including viewModel itself (call it in pageLoad or else):

ko.applyBindings();

And addItem should look like this:

addItem: function () {
    viewModel.items.push(new Item(0, "New", 5.00));
},

Because using 'this' won't work here.

Then, custom binder should look like this (token from another example somewhere):

ko.bindingHandlers.slickGrid = {
init: function (element, valueAccessor) {
    var settings = valueAccessor();
    var data = ko.utils.unwrapObservable(settings.data);
    var columns = ko.utils.unwrapObservable(settings.columns);
    var options = ko.utils.unwrapObservable(settings.options) || {};
    grid = new Slick.Grid(element, data, columns, options);
},
update: function (element, valueAccessor, allBindingAccessor, viewModel) {
    var settings = valueAccessor();
    var data = ko.utils.unwrapObservable(settings.data); //just for subscription
    grid.setData(data, true);
    grid.resizeCanvas(); // NB Very important for when a scrollbar appears
    grid.render();
}

}

Also, I had a problem that elements were added, but I couldn't saw the result. After some research slickgrid's sources I found this solution:

<div id="grid" class="grid-canvas" data-bind="slickGrid: { 
                                                        data: viewModel.items, 
                                                        columns: viewModel.columns, 
                                                        options: { 
                                                                    enableColumnReorder: false,
                                                                    rowHeight: 20, 
                                                                    enableAddRow: true,
                                                                    autoHeight: true
                                                                 } }"></div>
<a href="#" class="btn-link" data-bind="click: viewModel.addItem">Add Item</a>

Because somehow by default grid-viewport had 0px height :) Just added some options during binding.

Schnapz
  • 1,208
  • 13
  • 10
  • 404 Not Found - http://mleibman.github.io/SlickGrid/lib/jquery.event.drag-2.0.min.js" on jsfiddle – Daniël Tulp Jul 03 '15 at 09:28
  • Sorry, but I think those scripts were moved somewhere, and I also cannot find them at my computer... You could try latest version of SlickGrid from Github maybe it could help you => https://github.com/mleibman/SlickGrid – Schnapz Jul 06 '15 at 14:05