使用 Knockoutjs 的数据表数据绑定
Datatable data binding using knockoutjs
我想使用datatable knockoutjs绑定将数据呈现到表中。我正在使用下面的链接和代码将数据呈现到表中。http://datatables.net/dev/knockout/
我在上面的例子中所做的唯一更改是在渲染年龄数据时,我在年龄列中添加了输入框,用于记录和表格底部的更新按钮,以便用户可以更改他的年龄并单击更新按钮数据应该自动更新,在下一页它应该反映在表中。
面临的问题是我无法更新本地 js"人"模型,因此无法使用 knockoutjs 绑定更新的数据。
ko.observableArray.fn.subscribeArrayChanged = function(addCallback, deleteCallback) {
var previousValue = undefined;
this.subscribe(function(_previousValue) {
previousValue = _previousValue.slice(0);
}, undefined, 'beforeChange');
this.subscribe(function(latestValue) {
var editScript = ko.utils.compareArrays(previousValue, latestValue);
for (var i = 0, j = editScript.length; i < j; i++) {
switch (editScript[i].status) {
case "retained":
break;
case "deleted":
if (deleteCallback)
deleteCallback(editScript[i].value);
break;
case "added":
if (addCallback)
addCallback(editScript[i].value);
break;
}
}
previousValue = undefined;
});
};`
`var data = [
{ id: 0, first: "Allan", last: "Jardine", age: 86 },
{ id: 1, first: "Bob", last: "Smith", age: 54 },
{ id: 2, first: "Jimmy", last: "Jones", age: 32 }
]; `
`var Person = function(data, dt) {
this.id = data.id;
this.first = ko.observable(data.first);
this.last = ko.observable(data.last);
this.age = ko.observable(data.age);
// Subscribe a listener to the observable properties for the table
// and invalidate the DataTables row when they change so it will redraw
var that = this;
$.each( [ 'first', 'last', 'age' ], function (i, prop) {
that[ prop ].subscribe( function (val) {
// Find the row in the DataTable and invalidate it, which will
// cause DataTables to re-read the data
var rowIdx = dt.column( 0 ).data().indexOf( that.id );
dt.row( rowIdx ).invalidate();
} );
} );
};
$(document).ready(function() {
var people = ko.mapping.fromJS( [] );
//loadData();
var dt = $('#example').DataTable( {
"bPaginate": false,
"bInfo" : false,
"bAutoWidth" : false,
"sDom" : 't',
"columns": [
{ "data": 'id' },
{ "data": 'first' },
{ "data": 'age',
"mRender": function (data, type, row ) {
var html = '<div style="display:inline-flex">' +
'<input type="text" class="headerStyle h5Style" id="ageId" value="'+data()+'"/>' +
'</div>';
return html;
}
}
]
} );
// Update the table when the `people` array has items added or removed
people.subscribeArrayChanged(
function ( addedItem ) {
dt.row.add( addedItem ).draw();
},
function ( deletedItem ) {
var rowIdx = dt.column( 0 ).data().indexOf( deletedItem.id );
dt.row( rowIdx ).remove().draw();
}
);
// Convert the data set into observable objects, and will also add the
// initial data to the table
ko.mapping.fromJS(
data,
{
key: function(data) {
var d = data;
return ko.utils.unwrapObservable(d.id);
},
create: function(options) {
return new Person(options.data, dt);
}
},
people
);
} );
这是这样做的方法...我做了一个jsfiddle显示这个:
编辑:最近找到了一种使用香草敲除获得此绑定的方法。我已经在最新版本的挖空 (3.4) 上对此进行了测试,只需使用此绑定和挖空数据表即可!
ko.bindingHandlers.dataTablesForEach = {
page: 0,
init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
valueAccessor().data.subscribe(function (changes) {
var table = $(element).closest('table').DataTable();
ko.bindingHandlers.dataTablesForEach.page = table.page();
table.destroy();
}, null, 'arrayChange');
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, allBindings, viewModel, bindingContext) {
var options = ko.unwrap(valueAccessor()),
key = 'DataTablesForEach_Initialized';
ko.unwrap(options.data); // !!!!! Need to set dependency
ko.bindingHandlers.foreach.update(element, valueAccessor, allBindings, viewModel, bindingContext);
(function() {
console.log(options);
var table = $(element).closest('table').DataTable(options.dataTableOptions);
if (options.dataTableOptions.paging) {
if (table.page.info().pages - ko.bindingHandlers.dataTablesForEach.page == 0)
table.page(--ko.bindingHandlers.dataTablesForEach.page).draw(false);
else
table.page(ko.bindingHandlers.dataTablesForEach.page).draw(false);
}
})();
if (!ko.utils.domData.get(element, key) && (options.data || options.length))
ko.utils.domData.set(element, key, true);
return { controlsDescendantBindings: true };
}
};
JSFiddle
我用解决方案做了一个小提琴
http://jsfiddle.net/Jarga/hg45z9rL/
单击"更新"将在按钮下方以文本形式显示当前挖空模型。
缺少的是通过在渲染函数中添加侦听器将文本框的更改链接到可观察量。此外,每行的文本框都被赋予了相同的 ID,这也不是一个好主意。(注意:事件别名只是为了防止与其他处理程序发生冲突)
更改渲染函数以构建有用的 id 并添加以下内容应该有效:
$('#' + id).off('change.grid')
$('#' + id).on('change.grid', function() {
row.age($(this).val());
});
理想情况下,Knockout 会为您处理这个问题,但由于您没有调用 applyBindings,也没有为 html 元素创建数据绑定属性,因此 Knockout 在这里真正为您提供的是可观察的模式。
编辑:附加解决方案
再研究一下,你可以让 Knockout 通过将 data-bind
属性添加到模板中并将你的挖空模型绑定到表元素来处理渲染。
var html = '<div style="display:inline-flex">' +
'<input type="text" class="headerStyle h5Style" id="' + id + '" data-bind="value: $data[' + cell.row + '].age"/>'
和
ko.applyBindings(people, document.getElementById("example"));
这也会在构造Person
对象时删除整个自定义订阅调用。
这是第二个解决方案的另一个小提琴:
http://jsfiddle.net/Jarga/a1gedjaa/
我觉得这简化了解决方案。 但是,我不知道它的性能如何,也没有用分页测试过它,因此可能需要做额外的工作。 使用此方法,mRender函数永远不会重新执行,并且输入的DOM操作完全通过挖空完成。
这是一个简单的解决方法,它重新绑定挖空中的数据,然后销毁/重新创建数据表:
// Here's my data model
var ViewModel = function() {
this.rows = ko.observable(null);
this.datatableinstance = null;
this.initArray = function() {
var rowsource1 = [
{ "firstName" : "John",
"lastName" : "Doe",
"age" : 23 },
{ "firstName" : "Mary",
"lastName" : "Smith",
"age" : 32 }
];
this.redraw(rowsource1);
}
this.swapArray = function() {
var rowsource2 = [
{ "firstName" : "James",
"lastName" : "Doe",
"age" : 23 },
{ "firstName" : "Alice",
"lastName" : "Smith",
"age" : 32 },
{ "firstName" : "Doug",
"lastName" : "Murphy",
"age" : 40 }
];
this.redraw(rowsource2);
}
this.redraw = function(rowsource) {
this.rows(rowsource);
var options = { paging: false, "order": [[0, "desc"]], "searching":true };
var datatablescontainer = $('#datatablescontainer');
var html = $('#datatableshidden').html();
//Destroy datatable
if (this.datatableinstance) {
this.datatableinstance.destroy();
datatablescontainer.empty();
}
//Recreate datatable
datatablescontainer.html(html);
this.datatableinstance = datatablescontainer.find('table.datatable').DataTable(options);
}
};
ko.applyBindings(new ViewModel("Planet", "Earth")); // This makes Knockout get to work
https://jsfiddle.net/benjblack/xty5y9ng/
- Knockout.js复杂的表数据绑定
- 访问表单控制AngularJS中的值,而不绑定数据
- 显示带有角度 js 数据绑定表单的引导框
- 角度 - 将数据绑定到表单中
- 在提交时将数据绑定到表单
- 使用 Knockoutjs 的数据表数据绑定
- 如何使用 knockoutjs 映射插件对绑定到表的数据进行排序
- 复选框列出数据绑定并设置表单提交的复选框
- Knockout JS-将数据绑定到我的表
- 使用angularjs、jquery、json、ajax基于下拉选择绑定html表数据
- 如何在每个表行上放置click事件,并将结果作为参数传递,以将新数据绑定到另一个源
- 在html表的foreach绑定中,是否有可能将数据绑定到一个带有knockout的select下拉列表?
- 重新绑定数据表
- 通过数据绑定实现固定的表列数
- 删除映射和foreach数据绑定表上的按钮,缺少对视图模型的引用
- 使用ForEach将数据绑定到表
- js:不能将数据数组绑定到表单
- 获取html表中按钮的数据绑定值
- 第一次单击按钮时,它不会将数据绑定到表中
- 解析json对象并将数据绑定到表单字段