Syncfusion Essential JS库中的网格小部件(' ejGrid')支持Knockout.js,但只有当数据源是可观察的普通对象数组时,它才会起作用。如果数据源是可观察的视图模型数组,我该如何使它工作?例如:
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/
在上面的小提琴中,第一个网格使用一个可观察的普通对象数组,显示正常,我们可以使用'删除行'删除行来删除行。然而,按钮通过“变异行”变换行的一个字段。按钮不起作用(所以它不应该)。第二个网格使用一个可观察的视图模型数组,因此实现了“变异行”。按钮应该工作,但网格似乎试图显示可观察对象而不是它们的当前值。
答案 0 :(得分:3)
1:“第二个网格使用一个可观察的视图模型数组,因此'Mutate Row'按钮的实现应该有效,但网格似乎试图显示可观察对象而不是它们的当前值。”
Essential JavaScript Grid不支持在网格单元格中呈现KO可观察字段。但我们可以通过以下解决方法来满足您的要求。
//Workaround to show observable values in grid.
var oldToString = Function.prototype.toString;
Function.prototype.toString = function() {
if(ko.isObservable(this))
return this();
return oldToString.call(this);
}
使用上述解决方法将使可观察值显示在网格单元格中。
2:“第一个网格使用一个可观察的普通对象数组,显示正常,我们可以使用'删除行'按钮通过敲除删除行,但是,通过'变异行'按钮改变行的字段不起作用(所以它不应该)“
这是因为ejGrid
将保持数组的长度而不是数组值的状态,因此更改网格外的字段值将不会更新UI。如果要在网格中显示更新的值,则必须按如下方式刷新网格。
$('#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);
//Need to refresh grid to show updated value.
$("#Grid2").ejGrid("refreshContent");
});
答案 1 :(得分:1)
如果您在数据源上调用<body ng-controller="MyController">
<div style="width:90%;height:150px;border:1px solid red;overflow:auto">
<div ng-repeat="n in name">{{n.name}}</div>
</div>
,则会重新检查observableArray并更新网格。
valueHasMutated
有了这个,你不需要让各个数据项都是可观察的,但我想出了一种让ejGrid处理observable的有趣方法。如果使用Object.defineProperty为属性定义getter和setter,则赋值的语法与使用普通变量的语法相同,但它是使用observable实现的。
$('#mutate').click(function () {
// mutating the field does nothing (since it's not observable)
(gridData.dataSource())[0].OrderID = 999999;
gridData.dataSource.valueHasMutated();
});
现在,任何dataSource的更新语法都是相同的。
function observableToProperty(obj, data, propertyName) {
var observable = ko.observable(data[propertyName]);
Object.defineProperty(obj, propertyName, {
get: observable,
set: observable
});
}
var Order = function (data) {
var self = this;
observableToProperty(self, data, 'OrderID');
observableToProperty(self, data, 'CustomerID');
observableToProperty(self, data, 'ShipCity');
observableToProperty(self, data, 'Freight');
observableToProperty(self, data, 'EmployeeID');
};
在这种情况下,使用observable 没有优势,而且observable是完全私有的,所以你甚至不能订阅它们。但是如果你愿意的话,你可以让它们可以访问并对它们做一些有用的事情并且您可以像绑定的observables一样使用绑定中的属性。
如果不重写ejGrid bindingHandler,则无法使网格单元单独响应其内容的更新。即使包装它也没有用,因为你无法访问它在单元级别所做的事情(如果有的话)。因此,通知可观察的阵列,事情发生了变化是你能够合理做到的最好的事情。