Twitter bootstrap 基础数据更改时引导数据表未刷新(敲除绑定)

Twitter bootstrap 基础数据更改时引导数据表未刷新(敲除绑定),twitter-bootstrap,knockout.js,datatable,Twitter Bootstrap,Knockout.js,Datatable,我正在使用knockout将我的数据绑定到表中,在页面启动时,一切都正常。当我通过调用getDataByFilter()函数更改基础数据时,datatable数据通过敲除得到刷新,一切都正常工作 当我使用$('#datatable_requirement').datatable()添加分页和排序时,事情开始损坏。每次我触发getDataByFilter()函数来检索新数据时,新数据都会在现有数据的基础上堆叠,排序和搜索不再起作用。Google around仍然找不到任何解决方案:( 这是我的视图

我正在使用knockout将我的数据绑定到表中,在页面启动时,一切都正常。当我通过调用getDataByFilter()函数更改基础数据时,datatable数据通过敲除得到刷新,一切都正常工作

当我使用$('#datatable_requirement').datatable()添加分页和排序时,事情开始损坏。每次我触发getDataByFilter()函数来检索新数据时,新数据都会在现有数据的基础上堆叠,排序和搜索不再起作用。Google around仍然找不到任何解决方案:(

这是我的视图和视图模型

HTML:


Knockout需要完全控制DOM,因此,当您想要将jQuery库加入到具有相同功能的混合中时,您需要做一些额外的工作,以确保它们不会互相攻击。通常,您是以绑定的形式这样做的

DataTables提供了一个:

//Helper函数,以便我们知道发生了什么变化
// http://stackoverflow.com/questions/12166982
ko.observeArray.fn.subscriberRayChanged=函数(addCallback,deleteCallback){
var previousValue=未定义;
this.subscribe(函数(\u previousValue){
previousValue=_previousValue.slice(0);
},未定义“变更前”);
this.subscribe(函数(最新值){
var editScript=ko.utils.compararrays(previousValue,latestValue);
for(var i=0,j=editScript.length;i
我以前看过这个例子,但我不知道如何集成到我的代码中。我不是逐行添加或逐项删除。我是通过ajax调用将一组数据重新分配到我的淘汰Observerray中。你介意给出更多提示吗?我尝试将其集成到我的代码中,但没有成功,没有成功:对不起,我是新来的knockout@user3082385我没有使用DataTables,但是从快速查看文档来看,它可能适合您的用例。
<!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>
<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);
                });
}
// 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();
} );