简体   繁体   English

Knockout ViewModel更改时更新jquery DataTable

[英]Update jquery DataTable when Knockout ViewModel change

I have a Datatable that takes data from Knockout ViewModel array. 我有一个数据表,它从Knockout ViewModel数组中获取数据。 New rows are added fine when I push new objects to the array, but when an object in that array is changed, the row isn't being updated. 当我将新对象推送到数组时,可以很好地添加新行,但是当该数组中的对象更改时,该行不会被更新。

The relecent ViewModel code: 相关的ViewModel代码:

  .....
  self.Products = ko.observableArray();
  .....

Sample data (eg result of ko.toJSON(VM.Products()) ): 样本数据(例如ko.toJSON(VM.Products())的结果):

  "[
  {"Price":"114.28","Name":"Pearls","Description":"Little and big","Quantity":3},
  {"Price":"117.55","Name":"Silver","Description":"Sliver Coins","Quantity":2},
  {"Price":"166.09","Name":"Phone","Description":"Nokia","Quantity":2},
  {"Price":"169.36","Name":"Wood","Description":"Northen forest wood","Quantity":1}
  ]"

Then Datatable code: 然后是Datatable代码:

  var CartDt = $("#PurchasedPrdTbl").DataTable({        
    pageLength: 5,      
    aoData: ko.toJSON(VM.Products()),
    columns: [
        { "title": 'Price' },
        { "title": 'Name' },
        { "title": 'Description' },
        { "title": 'Quantity' },
        {
            "className": 'remove-details-control',
            "orderable": false,
            "data": null,
            "defaultContent": '',
            "title": "Sell Me!",
            "fnRender": function (oObj) {

                return oObj.aData;
            }
        }
    ]
});

I'v tried ajax.reload but it didn't helped. 我尝试过ajax.reload,但没有帮助。

Any ideas would be great, thanks. 任何想法都很好,谢谢。

EDIT: 编辑:

I'm trying fnUpdate ( source ) like this: 我正在尝试像这样的fnUpdate( source ):

 CartDt.fnUpdate([{"Price":"114.28","Name":"Pearls","Description":"Little and big","Quantity":3}],1);

But I get this: Uncaught TypeError: undefined is not a function 但是我得到了:Uncaught TypeError:undefined不是一个函数

This is because the html that is bound to your knockout observable array is mangled when datatables is initialized... The html is copied and reformatted to be "datatables" after initialization. 这是因为初始化数据表时会损坏绑定到可剔除可观察数组的html。初始化后,将html复制并重新格式化为“ datatables”。 so the elements that you view after datatables initialization are not the same elements that knockout has bound to. 因此,在初始化数据表后查看的元素与敲除绑定的元素不同。 I have created a custom binding to use datatables with knockout. 我创建了一个自定义绑定以将数据表与敲除一起使用。 it is dependent upon a fork of knockout which adds before render all and after render all events. 它取决于剔除的分支,该分支在渲染所有事件之前和渲染所有事件之后添加。 I have created a pull request with the knockout git hub repository. 我已经使用淘汰赛git hub存储库创建了一个请求请求。 If the below solution helps you please leave a comment on the pull request to get it merged into knockout 3.4... thanks. 如果以下解决方案对您有所帮助,请在拉取请求中留下评论,以将其合并到淘汰赛3.4中...谢谢。

fiddle of working solution 工作解决方案

my pull request 我的请求

ko.bindingHandlers.DataTablesForEach = {

        init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
             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, allBindingsAccessor, viewModel, bindingContext) {

            var value = ko.unwrap(valueAccessor()),
            key = "DataTablesForEach_Initialized";

            var newValue = function () {
                return {
                    data: value.data || value,
                    beforeRenderAll: function (el, index, data) {

                        if (ko.utils.domData.get(element, key)) {
                            $(element).closest('table').DataTable().clear();
                            $(element).closest('table').DataTable().destroy();
                        }
                    },
                    afterRenderAll: function (el, index, data) {
                        $(element).closest('table').DataTable(value.options);
                    }

                };
            };

            ko.bindingHandlers.foreach.update(element, newValue, allBindingsAccessor, viewModel, bindingContext);

            //if we have not previously marked this as initialized and there is currently items in the array, then cache on the element that it has been initialized
            if (!ko.utils.domData.get(element, key) && (value.data || value.length)) {
                ko.utils.domData.set(element, key, true);
            }

            return { controlsDescendantBindings: true };
        }
    };

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM