Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/476.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 使用knockoutjs的Datatable数据绑定_Javascript_Jquery_Knockout.js_Jquery Datatables - Fatal编程技术网

Javascript 使用knockoutjs的Datatable数据绑定

Javascript 使用knockoutjs的Datatable数据绑定,javascript,jquery,knockout.js,jquery-datatables,Javascript,Jquery,Knockout.js,Jquery Datatables,我想使用datatable knockoutjs绑定将数据呈现到表中。 我使用下面的链接和代码将数据呈现到表中 在上面的示例中,我所做的唯一更改是,在呈现年龄数据时,我在表底部的age col for Every record和Updatebutton中添加了输入框,以便用户可以更改其年龄并单击更新按钮,数据应自动更新,在下一页中,它应反映在表中 我面临的问题是,我无法更新本地js“people”模型,因此无法使用knockoutjs绑定更新的数据 ko.observableArray.fn.s

我想使用datatable knockoutjs绑定将数据呈现到表中。 我使用下面的链接和代码将数据呈现到表中

在上面的示例中,我所做的唯一更改是,在呈现年龄数据时,我在表底部的age col for Every record和Updatebutton中添加了输入框,以便用户可以更改其年龄并单击更新按钮,数据应自动更新,在下一页中,它应反映在表中

我面临的问题是,我无法更新本地js“people”模型,因此无法使用knockoutjs绑定更新的数据

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


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

   `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);

    // 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();
        } );
    } ); 
};

    $(document).ready(function() {

var people = ko.mapping.fromJS( [] );
    //loadData();

    var dt = $('#example').DataTable( {
        "bPaginate": false,
        "bInfo" : false,
        "bAutoWidth" : false,
        "sDom" : 't',
        "columns": [
            { "data": 'id' },
            { "data": 'first' },
            { "data": 'age',
                "mRender": function (data, type, row ) {    
                                var html = '<div style="display:inline-flex">' + 
                                                '<input type="text" class="headerStyle h5Style" id="ageId" value="'+data()+'"/>' +
                                                '</div>';

                                  return html;
                            } 
             }
        ]


    } );


    // 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) {
            var d = data;

                return ko.utils.unwrapObservable(d.id);        
            },
            create: function(options) {
                return new Person(options.data, dt);
            }    
        },
        people
    );



} );
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
我摆弄了一个解决方案

单击“更新”将在按钮下方以文本形式显示当前淘汰模型

缺少的是通过在渲染函数中添加侦听器将文本框的更改链接到可观察对象。此外,每行的文本框都被赋予相同的id,这也不是一个好主意。(注意:事件别名只是为了防止与其他处理程序发生冲突)

更改渲染函数以生成有用的ID并添加以下内容应该可以:

$('#' + id).off('change.grid')
$('#' + id).on('change.grid', function() {
    row.age($(this).val());
});
理想情况下,Knockout会为您处理这个问题,但由于您没有调用applyBindings,也没有为html元素创建数据绑定属性,所以Knockout在这里真正提供的是可观察的模式

编辑:附加解决方案

再仔细研究一下,您可以通过将
数据绑定
属性添加到模板中并将您的Knockout模型绑定到table元素,让Knockout处理呈现

var html = '<div style="display:inline-flex">' + 
    '<input type="text" class="headerStyle h5Style" id="' + id + '" data-bind="value: $data[' + cell.row + '].age"/>'
这在构造
Person
对象时也会删除整个自定义订阅调用

下面是第二个解决方案的另一个问题:


我觉得这简化了解决方案。然而,我不知道它的执行效率有多高,也没有用分页测试过它,因此可能需要做额外的工作。使用这种方法,mRender函数永远不会重新执行,输入的DOM操作完全是通过敲除完成的。

这是一种方法。。。我制作了一个JSFIDLE,展示了以下内容:

编辑:最近想出了一种方法来获得这种绑定使用香草敲除。我已经在最新版本的knockout(3.4)上测试过了,只要使用这个绑定,knockout datatables就可以工作了

ko.bindingHandlers.dataTablesForEach = {
page: 0,
init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {       
    valueAccessor().data.subscribe(function (changes) {
        var table = $(element).closest('table').DataTable();
        ko.bindingHandlers.dataTablesForEach.page = table.page();
        table.destroy();
    }, null, 'arrayChange');           
    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, allBindings, viewModel, bindingContext) {       
    var options = ko.unwrap(valueAccessor()),
        key = 'DataTablesForEach_Initialized';
    ko.unwrap(options.data); // !!!!! Need to set dependency     
    ko.bindingHandlers.foreach.update(element, valueAccessor, allBindings, viewModel, bindingContext);
    (function() {
        console.log(options);
        var table = $(element).closest('table').DataTable(options.dataTableOptions);
        if (options.dataTableOptions.paging) {
            if (table.page.info().pages - ko.bindingHandlers.dataTablesForEach.page == 0)
                table.page(--ko.bindingHandlers.dataTablesForEach.page).draw(false);               
            else
                table.page(ko.bindingHandlers.dataTablesForEach.page).draw(false);               
        }
    })();
    if (!ko.utils.domData.get(element, key) && (options.data || options.length))
        ko.utils.domData.set(element, key, true);
    return { controlsDescendantBindings: true };
}
})


这里有一个简单的解决方法,可以在knockout中重新绑定数据,然后销毁/重新创建数据表:

// Here's my data model
var ViewModel = function() {
    this.rows = ko.observable(null);
    this.datatableinstance = null;

    this.initArray = function() {
            var rowsource1 =  [   
                    { "firstName" : "John",  
                      "lastName"  : "Doe",
                      "age"       : 23 },

                    { "firstName" : "Mary",  
                      "lastName"  : "Smith",
                      "age"       : 32 }
                  ];         
        this.redraw(rowsource1);

    }

    this.swapArray = function() {
      var rowsource2 =  [   
                      { "firstName" : "James",  
                        "lastName"  : "Doe",
                        "age"       : 23 },

                      { "firstName" : "Alice",  
                        "lastName"  : "Smith",
                        "age"       : 32 },

                      { "firstName" : "Doug",  
                        "lastName"  : "Murphy",
                        "age"       : 40 }

                    ];       
        this.redraw(rowsource2);
    }

    this.redraw = function(rowsource) {
      this.rows(rowsource);


      var options = { paging: false, "order": [[0, "desc"]], "searching":true };
      var datatablescontainer = $('#datatablescontainer');
      var html = $('#datatableshidden').html();

      //Destroy datatable
      if (this.datatableinstance) {
        this.datatableinstance.destroy();
        datatablescontainer.empty();
      }

      //Recreate datatable
      datatablescontainer.html(html);
      this.datatableinstance = datatablescontainer.find('table.datatable').DataTable(options);    
    }

};

ko.applyBindings(new ViewModel("Planet", "Earth")); // This makes Knockout get to work

Html代码:ID名称年龄更新谢谢!谢谢你的努力:-)谢谢jarga!我会继续找你的零钱
// Here's my data model
var ViewModel = function() {
    this.rows = ko.observable(null);
    this.datatableinstance = null;

    this.initArray = function() {
            var rowsource1 =  [   
                    { "firstName" : "John",  
                      "lastName"  : "Doe",
                      "age"       : 23 },

                    { "firstName" : "Mary",  
                      "lastName"  : "Smith",
                      "age"       : 32 }
                  ];         
        this.redraw(rowsource1);

    }

    this.swapArray = function() {
      var rowsource2 =  [   
                      { "firstName" : "James",  
                        "lastName"  : "Doe",
                        "age"       : 23 },

                      { "firstName" : "Alice",  
                        "lastName"  : "Smith",
                        "age"       : 32 },

                      { "firstName" : "Doug",  
                        "lastName"  : "Murphy",
                        "age"       : 40 }

                    ];       
        this.redraw(rowsource2);
    }

    this.redraw = function(rowsource) {
      this.rows(rowsource);


      var options = { paging: false, "order": [[0, "desc"]], "searching":true };
      var datatablescontainer = $('#datatablescontainer');
      var html = $('#datatableshidden').html();

      //Destroy datatable
      if (this.datatableinstance) {
        this.datatableinstance.destroy();
        datatablescontainer.empty();
      }

      //Recreate datatable
      datatablescontainer.html(html);
      this.datatableinstance = datatablescontainer.find('table.datatable').DataTable(options);    
    }

};

ko.applyBindings(new ViewModel("Planet", "Earth")); // This makes Knockout get to work