使用 jquery.dataTables 从 observableArray 中删除项目后 UI 不更新

Posted

技术标签:

【中文标题】使用 jquery.dataTables 从 observableArray 中删除项目后 UI 不更新【英文标题】:UI not update after removing item from observableArray with jquery.dataTables 【发布时间】:2016-10-21 19:31:27 【问题描述】:

我正在使用jquery.dataTablesknockout js 将数据绑定到表。

observableArray 中删除项目后,UI 不会更新。因为我将数据绑定到jquery.Datatable,所以可以重新初始化表;所以我通过调用TableManaged.init(); 方法重新初始化表,但它正在生成警告cannot reinitialise datatable

下面是我的代码。

function PatientVM(vm) 
  self.MDSPatientId = ko.observable(vm.MDSPatientId());
  self.PatientNumber = ko.observable(vm.PatientNumber());
  self.PrescribingDay = ko.observable(vm.PrescribingDay());
  self.OneWeekItems = ko.observable(vm.OneWeekItems());
  self.DeliveryDay = ko.observable(vm.DeliveryDay());
  self.IsActive = ko.observable(vm.IsActive());
  self.WeekColor = ko.observable(vm.WeekColor());
  self.PatientName = ko.observable(vm.PatientName());
  self.FullAddress = ko.observable(vm.FullAddress());


function Patients(vm) 
  var self = this;
  self.PatientList = ko.observableArray();

  if (vm.PatientList() != null) 
    for (i = 0; i < vm.PatientList().length; i++) 
      var p = new PatientVM(vm.PatientList()[i]);
      self.PatientList.push(p);
    
  

  self.DeletePatient = function(patient) 
    var result = confirm("Want to delete?");
    if (result) 
      $.ajax(
        url: '@Url.Action("DeleteMDSPatient", "Patient")',
        cache: false,
        type: 'GET',
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        data: 
          'MDSPatientId': patient.MDSPatientId()
        ,
        success: function(response) 
          if (response.Result == 3) 
            self.PatientList.remove(patient);
            ShowToastMessage("Patient has been deleted successfully", "Success", true);
          
        ,
        error: function(errorThrown) 
      );
    
  


$(document).ready(function() 
  ko.applyBindings(new Patients(ko.mapping.fromJS(@html.Raw(JsonConvert.SerializeObject(Model)))));
  App.init();
  TableManaged.init();
);
<table class="table table-striped table-bordered table-hover" id="sample_3" style="line-height:22px;table-layout:fixed;overflow-x:hidden;">
  <thead>
    <tr style="background-color:#348fe2">
      <th style="width:5%;text-align:center">
        <span class="showellipses">Active Patient</span>
      </th>
      <th style="width:10%"><span>Name</span>
      </th>
      <th style="width:20%"><span class="showellipses">Address</span>
      </th>
      <th style="width:10%"><span class="showellipses">PrescribingDay</span>
      </th>
      <th style="width:5%"><span class="showellipses">No. of items in four week</span>
      </th>
      <th style="width:10%"><span class="showellipses">Assembly Week</span>
      </th>
      <th style="width:10%"><span>Delivery Day</span>
      </th>
      <th style="width:5%">Action</th>
    </tr>
  </thead>
  <tbody data-bind="foreach:PatientList">
    <tr class="odd gradeX">
      <td style="text-align:center">
        <input type="checkbox" data-bind="checked:IsActive, click:ChangePatientStatus" class="checkboxes" />
      </td>
      <td>
        <span class="showellipses" data-bind="text:PatientName"></span>
      </td>
      <td>
        <span class="showellipses" data-bind="text:FullAddress"></span>
      </td>
      <td>
        <span data-bind="text:PrescribingDay"></span>
      </td>
      <td class="center">
        <span data-bind="text:OneWeekItems"></span>
      </td>
      <td>
        <span data-bind="text:WeekColor"></span>
      </td>
      <td>
        <span data-bind="text:DeliveryDay"></span>
      </td>
      <td>
        <a title="Edit" style="text-decoration:none" class="fa fa-edit" data-bind="attr:  'href': '@Url.Action(" PatientView ", "Patient ")?MDSPatientId=' + MDSPatientId()"></a>&nbsp;|
        <a title="Delete" style="text-decoration:none" class="fa fa-trash-o" data-bind="click:$parent.DeletePatient"></a>
      </td>
    </tr>
  </tbody>
</table>

【问题讨论】:

如果您真的想使用敲除来渲染您的表格,请考虑非常。 DataTables 有它自己非常强大的表格渲染引擎,你绝对应该使用它。在这种情况下,DataTables 和淘汰赛功能严重重叠和竞争,要让它们相互配合并不容易。明智的做法是只为页面的这一部分使用其中一个库,并且最终只使用 DataTables 会比其他方式容易得多。 【参考方案1】:

这是他们的文档link 中的一个示例。

您需要一个额外的步骤来通知 jquery 插件更新表。 基本上,您需要订阅数组更改并使删除的行无效。 他们建议使用帮助器来订阅 observable 数组,如下所示:

// Helper function so we know what has changed
// http://***.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;
    );
;

然后您需要订阅并响应数组更改:

self.PatientList.subscribeArrayChanged(
        function ( addedItem ) 
            dt.row.add( addedItem ).draw();
        ,
        function ( deletedItem ) 
            var rowIdx = dt.column( 0 ).data().indexOf( deletedItem.id );
            dt.row( rowIdx ).remove().draw();
        
    );

这是带有完整示例的plunk。

【讨论】:

这可能是该问题的一个很好的答案,但是链接往往会随着时间的推移而断开。如果您考虑将代码的相关部分复制粘贴到您的答案中,那就太好了。谢谢。 您链接到的答案非常旧,并且已被 knockout's native array change notifications 取代(自 3.0 版起可用)。 subscribeArrayChanged 函数是多余的。

以上是关于使用 jquery.dataTables 从 observableArray 中删除项目后 UI 不更新的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 jQuery DataTables 从数据库中显示特定数量的 HTML 表中的项目?

无法从 jQuery DataTables 中触发模式

我如何从 jQuery Datatables 调用 django 视图?

使用 jQuery DataTables 进行数据可视化

jQuery DataTables 是在单个请求中还是使用分页从数据库中获取所有数据?

jQuery DataTables - 删除标签