The grid widget ('ejGrid') in the Syncfusion Essential JS library supports Knockout.js, however it only appears to work when the data source is an observable array of plain objects. How do I make it work if the data source is an observable array of view models? For example:
var Order = function (data) {
var self = this;
self.OrderID = ko.observable(data.OrderID);
self.CustomerID = ko.observable(data.CustomerID);
self.ShipCity = ko.observable(data.ShipCity);
self.Freight = ko.observable(data.Freight);
self.EmployeeID = ko.observable(data.EmployeeID);
};
var rows =
[ {
OrderID: 10248,
CustomerID: "VINET",
ShipCity: "Reims",
Freight: 11.61,
EmployeeID: 4
}, {
OrderID: 10250,
CustomerID: "HANAR",
ShipCity: "Charleroi",
Freight: 65.83,
EmployeeID: 2
}, {
OrderID: 10251,
CustomerID: "VICTE",
ShipCity: "Reims",
Freight: 41.34,
EmployeeID: 1
}, {
OrderID: 10252,
CustomerID: "SUPRD",
ShipCity: "Madrid",
Freight: 51.3,
EmployeeID: 3
}, {
OrderID: 10253,
CustomerID: "HANAR",
ShipCity: "Rio de Janeiro",
Freight: 58.17,
EmployeeID: 3
} ];
var rows2 = $.map(rows, function (data) { return new Order(data); });
var gridData = {
dataSource: ko.observableArray(rows),
dataSource2: ko.observableArray(rows2)
};
ko.applyBindings(gridData);
$('#remove').click(function () {
// both these work fine, since the array is observable
gridData.dataSource.pop();
gridData.dataSource2.pop();
});
$('#mutate').click(function () {
// mutating the field does nothing (since it's not observable)
(gridData.dataSource())[0].OrderID = 999999;
// this should work, however the table is full of gibberish
(gridData.dataSource2)()[0].OrderID(999999);
});
JSFiddle: http://jsfiddle.net/hrapq7m2/
In the above fiddle, the first grid uses an observable array of plain objects, which displays ok and we can remove rows via knockout using the 'Remove Row' button, however, mutating a field of a row via the 'Mutate Row' button doesn't work (and so it shouldn't). The second grid uses an observable array of view models, and so the implementation of the 'Mutate Row' button should work, however the grid appears to be attempting to display the observable objects instead of their current values.
If you call
valueHasMutated
on your data source, the observableArray will be re-examined and the grid will update.With that, you don't need to have the individual data items be observables, but I came up with a kind of interesting way to make the ejGrid handle observables. If you define getters and setters for your properties using Object.defineProperty, the syntax for assignment is the same as if you have an ordinary variable, but it is implemented using the observable.
Now the update syntax is the same for either dataSource.
There is, in this case, no advantage to using the observable, and the observables are completely private, so you can't even subscribe to them. But you could make them accessible and do something useful with them if you wanted. And you can use the properties in bindings just like the underlying observables.
There is no way to make the grid cells respond individually to updates of their contents without rewriting the ejGrid bindingHandler. Even wrapping it doesn't help, because you don't have access to what (if anything) it does at the cell level. So notifying the observableArray that something has changed is the best you can reasonably do.
http://jsfiddle.net/hrapq7m2/4/