使用knockoutjs进行数据表数据绑定 [英] Datatable data binding using knockoutjs
问题描述
我想使用datatable knockoutjs绑定将数据呈现到表中。
我使用以下链接和代码将数据呈现到表中。 http://datatables.net/dev/knockout/
I want to render data into table using datatable knockoutjs binding. I am using the below link and code for rendering data into table. http://datatables.net/dev/knockout/
我在上面的示例中做的唯一更改是在渲染年龄数据时,我在age col中添加了输入框以供记录,而在表底部添加Updatebutton,以便用户可以更改其年龄并单击更新按钮数据应自动更新,并在下一页中反映在表格中。
The only change I did in above example is while rendering age data I have added input box in age col for ever record and Updatebutton at the bottom of table, so that user can change his age and click of update button data should be updated automatically and in next page it should reflect in table.
我面临的问题是我无法更新本地js人模型,因此无法使用knockoutjs绑定更新的数据。
The issue am facing is that i am unable to update local js "people" model and hence unable to bind updated data using 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
);
} );
推荐答案
我做了一个小提琴解决方案
I made a fiddle with a solution
http://jsfiddle.net/Jarga/hg45z9rL/
点击更新会将当前的淘汰模型显示为按钮下方的文本。
Clicking "Update" will display the current knockout model as text below the button.
缺少什么是通过在render函数中添加一个监听器来链接文本框到observable的更改。此外,每一行的文本框都被赋予相同的ID,这也不是一个好主意。 (注意:事件别名只是为了防止与其他处理程序发生冲突)
What was missing was the linking the change of the textbox to the observable by adding a listener in the render function. Also each row's textbox was being given the same id, which is not a good idea either. (Note: the event aliases are just to prevent collision with other handlers)
更改渲染函数以构建有用的ID并添加以下内容应该有效:
Changing the render function to build useful ids and adding the following should work:
$('#' + id).off('change.grid')
$('#' + id).on('change.grid', function() {
row.age($(this).val());
});
理想情况下,Knockout会为您处理此事,但因为您没有调用applyBindings,也没有创建数据绑定属性对于html元素,所有淘汰赛真正给你的是可观察的模式。
Ideally Knockout would handle this for you but since you are not calling applyBindings nor creating the data-bind attributes for the html elements all that knockout really gives you here is the observable pattern.
编辑:其他解决方案
通过在模板中添加 data-bind
属性并将敲除模型绑定到模板,您可以让Knockout处理渲染。表元素。
Looking into it a little bit more you can let Knockout handle the rendering by adding the data-bind
attribute into the template and binding your knockout model to the table element.
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 $ c时删除整个自定义订阅调用$ c>对象也是。
这是第二个解决方案的另一个小提琴:
Here is another fiddle with the 2nd solution:
http://jsfiddle.net/Jarga/a1gedjaa/
我觉得这样可以简化解决方案。但是,我不知道它的执行效率,也没有用分页测试它,所以可能需要做额外的工作。使用此方法,mRender函数永远不会被重新执行,并且输入的DOM操作完全使用knockout完成。
I feel like this simplifies the solution. However, i do not know how efficient it performs nor have i tested it with paging so additional work may need to be done. With this method the mRender function is never re-executed and the DOM manipulation for the input is done entirely with knockout.
这篇关于使用knockoutjs进行数据表数据绑定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!