这是JS代码:
function ProductViewModel() {
// Init.
var self = this;
self.products = ko.observableArray();
self.singleProduct = ko.observable();
var mappedProducts;
// Initialize table here.
$.getJSON("/admin/test", function(allData) {
mappedProducts = $.map(allData, function(item) { return new Product(item);});
self.products(mappedProducts);
self.oTable = $('#products-table').dataTable( {
"aoColumns": [
{ "bSortable": false, "mDataProp": null, sDefaultContent: '' },
{"mData": "name"},
{"mData": "dealer"},
{"mData": "cost"},
{"mData": "price"},
{ "bSortable": false, sDefaultContent: '' }
],
});
});
// Here i'm using the basic switch pattern, as from KO tutorials.
// This is intended for showing a single product form.
self.edit = function(product) {
self.singleProduct(product);
}
// This is intended to hide form and show list back.
self.list = function() {
self.singleProduct(null);
}
// This is the form save handler, actually does nothing
// but switch the view back on list.
self.doEdit = function(product) {
self.list();
}
}
// My model.
function Product(item) {
this.name = ko.observable(item.name);
this.dealer = ko.observable(item.dealer);
this.cost = ko.observable(item.cost);
this.price = ko.observable(item.price);
this.picture = ko.observable();
}
这是我的标记:
<table id="products-table" class="table table-striped table-bordered table-hover">
<thead>
<tr>
<th>Pic</th>
<th>Name</th>
<th>Dealer</th>
<th>Cost</th>
<th>Price</th>
<th>Actions</th>
</tr>
</thead>
<tbody data-bind="foreach: $parent.products">
<tr>
<td><span data-bind='ifnot: picture'>-</span></td>
<td><a data-bind="text: name"></a></td>
<td><span data-bind='text: dealer'></span></td>
<td><span data-bind='text: cost'></span></td>
<td><span data-bind='text: price'></span></td>
<td>
<button data-bind='click: $root.edit'><i class='icon-pencil'></i>
</button>
</td>
</tr>
</tbody>
</table>
当我点击编辑按钮,触发$ root.edit处理程序时,会显示一个表单,因为
<div data-bind='with: singleProduct'>
绑定我做了。在这个绑定中我有一个表单,带有
<input data-bind="value: name" type="text" id="" placeholder="Name"
> class="col-xs-10 col-sm-5">
字段。
问题:当我在输入字段中编辑值时,数据表中的相对行不会更新。我已经尝试了没有datatables插件的基本表,它确实有效,这意味着如果我更改了值,表中的行会正确更新。
这里有什么问题?
==编辑==
我发现将绑定点移动到表TD修复了问题,但仍然无法弄清楚原因。
<tr>
<td data-bind="text: name"></td>
<!-- More columns... -->
</tr>
上面的代码现在正常运行。为什么?
== EDIT2 ==
既然我已经解决了第一个问题,那就是第二个问题。我实现了我的“保存新”方法,如此
self.doAdd = function(product) {
$.ajax("/product/", {
data: ko.toJSON({ product: product }),
type: "post", contentType: "application/json",
success: function(result) { alert('ehh'); }
}).then(function(){
self.products.push(product); // <--- Look at this!
self.list();
});
}
self.products.push(product);在成功处理程序中正确地更新我的产品observable。然后,一个新行会自动添加到我的表中,这是个好消息。
坏消息是,一旦我在阵列中推送新产品,数据表控件(如搜索字段或可点击排序箭头)就会消失。为什么这样!?
答案 0 :(得分:1)
你有没有解决这个问题?
我多年来一直有类似的问题。
最后我的修复是使用ko.mapping.fromJS(实体)映射我的所有实体 - 然后连接所有必需的依赖项并确保任何更改都流过我的模型。
答案 1 :(得分:0)
http://jsfiddle.net/zachpainter77/4tLabu56/
ko.bindingHandlers.DataTablesForEach = {
init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
var nodes = Array.prototype.slice.call(element.childNodes, 0);
ko.utils.arrayForEach(nodes, function (node) {
if (node && node.nodeType !== 1) {
node.parentNode.removeChild(node);
}
});
return ko.bindingHandlers.foreach.init(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext);
},
update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
var value = ko.unwrap(valueAccessor()),
key = "DataTablesForEach_Initialized";
var newValue = function () {
return {
data: value.data || value,
beforeRenderAll: function (el, index, data) {
if (ko.utils.domData.get(element, key)) {
$(element).closest('table').DataTable().destroy();
}
},
afterRenderAll: function (el, index, data) {
$(element).closest('table').DataTable(value.options);
}
};
};
ko.bindingHandlers.foreach.update(element, newValue, allBindingsAccessor, viewModel, bindingContext);
//if we have not previously marked this as initialized and there is currently items in the array, then cache on the element that it has been initialized
if (!ko.utils.domData.get(element, key) && (value.data || value.length)) {
ko.utils.domData.set(element, key, true);
}
return { controlsDescendantBindings: true };
}
};
https://rawgit.com/zachpainter77/zach-knockout.js/master/zach-knockout.debug.js