Knockout ViewModel更改时更新jquery DataTable

时间:2015-02-03 09:13:11

标签: javascript jquery knockout.js

我有一个从Knockout ViewModel数组获取数据的Datatable。当我将新对象推送到数组时,新行被添加得很好,但是当更改该数组中的对象时,该行不会被更新。

相当的ViewModel代码:

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

示例数据(例如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}
  ]"

然后是数据表代码:

  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;
            }
        }
    ]
});

我试过ajax.reload,但没有帮助。

任何想法都会很棒,谢谢。

编辑:

我正在尝试这样的fnUpdate(source):

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

但我得到了这个:      未捕获的TypeError:undefined不是函数

1 个答案:

答案 0 :(得分:0)

这是因为当初始化数据表时,绑定到knockout observable数组的html会被破坏... html在初始化后被复制并重新格式化为“datatables”。所以在数据表初始化之后查看的元素与knockout绑定的元素不同。我创建了一个自定义绑定来使用带有敲除的数据表。它取决于在渲染全部和之后渲染所有事件之前添加的分组。我已经使用knockout git hub存储库创建了一个pull请求。如果以下解决方案对您有帮助,请对拉取请求发表评论,将其合并到淘汰赛中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 };
        }
    };