我正在使用knockout将我的数据绑定到表,并在页面启动时一切正常工作正常。当我通过调用getDataByFilter()函数更改基础数据时,数据表数据通过淘汰得到刷新,一切正常。
当我使用$('#datatable_requirement')添加分页和排序时,事情开始腐败.DataTable()。每当我触发getDataByFilter()函数来检索新数据时,新数据就会在现有数据的基础上保持堆栈,并且排序和搜索不再起作用。谷歌仍然无法找到任何解决方案:(
这是我的View和Viewmodel
HTML:
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
<a href="javascript:void(0);" data-bind="click: getDataByFilter('pass some filter set')">Get new data</a>
<table id="datatable_requirement" class="table table-striped table-bordered" width="100%">
<thead>
<tr>
<th class="hasinput" style="width:17%">
<input type="text" class="form-control" placeholder="Filter Id" />
</th>
<th class="hasinput" style="width:17%">
<input type="text" class="form-control" placeholder="Filter Name" />
</th>
<th class="hasinput" style="width:16%">
<input type="text" class="form-control" placeholder="Filter Status" />
</th>
</tr>
<tr>
<th data-class="expand">Id</th>
<th>Name</th>
<th data-hide="phone">Status</th>
</tr>
</thead>
<tbody>
<!-- ko foreach: requirements -->
<tr>
<td><span data-bind="text: ReqEtpDispIdPrefix() + '-' + ReqDispId()"></span></td>
<td><span data-bind="text: ReqName"></span></td>
<td><span data-bind="text: ReqSttName"></span></td>
</tr>
<!-- /ko -->
</tbody>
</table>
</body>
</html>
JavaScript的:
<script type="text/javascript">
$(document).ready(function () {
$.getJSON("/api/GetAllRequirementByFilter/", function (data){
var VM = new ViewModel(data);
ko.applyBindings(VM);
var responsiveHelper_datatable_requirement = undefined;
var otable = $('#datatable_requirement').DataTable({
"sDom": "<'dt-toolbar'<'col-xs-12 col-sm-6 hidden-xs'f><'col-sm-6 col-xs-12 hidden-xs'l>r>" +
"t" +
"<'dt-toolbar-footer'<'col-sm-6 col-xs-12 hidden-xs'i><'col-xs-12 col-sm-6'p>>",
"autoWidth": true,
"preDrawCallback": function () {
// Initialize the responsive datatables helper once.
if (!responsiveHelper_datatable_requirement) {
responsiveHelper_datatable_requirement = new ResponsiveDatatablesHelper($('#datatable_requirement'), breakpointDefinition);
}
},
"rowCallback": function (nRow) {
responsiveHelper_datatable_requirement.createExpandIcon(nRow);
},
"drawCallback": function (oSettings) {
responsiveHelper_datatable_requirement.respond();
}
});
// custom toolbar
$("div.toolbar").html('<div class="text-right"><img src="/Content/img/logo.png" alt="SmartAdmin" style="width: 111px; margin-top: 3px; margin-right: 10px;"></div>');
// Apply the filter
$("#datatable_requirement thead th input[type=text]").on('keyup change', function () {
otable
.column($(this).parent().index() + ':visible')
.search(this.value)
.draw();
});
});
})
</script>
视图模型:
var ViewModel = function (data) {
var self = this;
self.requirements = ko.observableArray([]);
self.requirements = ko.mapping.fromJS(data);
function ajaxHelper(uri, method, data) {
self.error(''); // Clear error message
return $.ajax({
type: method,
url: uri,
dataType: 'json',
contentType: 'application/json',
data: data ? JSON.stringify(data) : null
}).fail(function (jqXHR, textStatus, errorThrown) {
self.error(errorThrown);
});
}
self.getDataByFilter = function (item)
{
ajaxHelper('/api/someapi/'+ item, 'GET').done(function (data) {
ko.mapping.fromJS(data, self.requirements);
});
}
答案 0 :(得分:0)
Knockout需要完全控制DOM,所以当你想把jQuery库放到混合中时,你需要做一些额外的工作,以确保他们都不会踩到对方&# 39;脚趾。通常,你以绑定的形式这样做。
DataTables提供example for a Knockout integration:
// Helper function so we know what has changed
// http://stackoverflow.com/questions/12166982
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;
});
};
// Person object
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);
this.full = ko.computed(function() {
return this.first() + " " + this.last();
}, this);
// 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();
} );
} );
};
// Initial data set
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 }
];
$(document).ready(function() {
var people = ko.mapping.fromJS( [] );
var dt = $('#example').DataTable( {
columns: [
{ data: 'id' },
{ data: 'first()' },
{ data: 'age()' }
]
} );
// 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) {
return ko.utils.unwrapObservable(data.id);
},
create: function(options) {
return new Person(options.data, dt);
}
},
people
);
// Examples:
// Update a field
people()[0].first( 'Allan3' );
// Add an item
people.push( new Person( {
id: 3,
first: "John",
last: "Smith",
age: 34
}, dt ) );
// Remove an item
people.shift();
} );