简体   繁体   English

将淘汰表与Datatables Ajax源一起使用

[英]Using Knockout with Datatables Ajax source

I have a data table like this and would like to make my data table rows have knockout observable properties. 我有一个这样的数据表,并希望使我的数据表行具有可观察到的剔除属性。 What is the best approach to be able to data-bind:"click" on a row in a datatable. 能够进行数据绑定的最佳方法是:“单击”数据表中的一行。 I have seen a datatables knockout binding but it doesnt seem to support ajax sources. 我见过一个数据表敲除绑定,但它似乎不支持Ajax源。 Any ideas I tried using the foreach and template bindings to create the table and having datatables initialize it from the DOM but it removes the binding I had so when I click now it does nothing. 我尝试过使用foreach和模板绑定创建表并让数据表从DOM初始化它的任何想法,但是它删除了我拥有的绑定,因此当我单击现在它不会执行任何操作。 Also seems slow. 似乎也很慢。 I would like to use AJAX or JS Array. 我想使用AJAX或JS Array。

         {            
            "bDeferRender" : true,
            "bProcessing" : true,
            "sDom": '<"top"r>t<"bottom"lp><"clear">',
            "oLanguage" : {
            "sLoadingRecords" : "&nbsp;",
                "sProcessing" : processDialog
            },
            "sAjaxSource":'/get_statistics',
            "sAjaxDataProp": 'landing_page_statistics',
            "fnServerParams": function (aoData) {
                aoData.push({"name": "start_date", "value": startDateEl.val()});
                aoData.push({"name": "end_date", "value": endDateEl.val()});
            },
            "aoColumns" : [
                {"mData" : "status", "sWidth": "6%"},
                {"mData" : "name"},
                {"mData" : "url"},
                {"mData" : "pageViews", "sWidth": "15%"},
                {"mData" : "leads", "sWidth": "5%"},
                {"mData" : "convRate", "sWidth": "12%"}
            ],
            "fnRowCallback": function (nRow, aData, iDisplayIndex) {
                renderDataTableRow(nRow, aData, iDisplayIndex);
            },
            "fnFooterCallback" : function (nFoot, aData, iStart, iEnd, aiDisplay) {
               renderDataTableTotalsRow(nFoot, aData, iStart, iEnd, aiDisplay);
            },
            "fnDrawCallback": function( oSettings ) {
                // status tooltips
                $('.lp-status').tooltip();
            }
        }

I'm not sure if I get the point in your question, and if I do my answer feels like cheating, merely pointing to the relevant sources. 我不确定我是否能理解你的问题,如果我这样做,我的回答就像是在作弊,只是指向相关资料。 In any case, here goes. 无论如何,这是可行的。

Your first option is to use load and save AJAX data to and from your view models manually. 您的第一个选择是使用加载模型并将 AJAX数据手动保存到视图模型中或从视图模型中保存 The related tutorial does a pretty decent job of explaining things. 相关教程在解释事物方面做得相当不错。 Loading comes down to: 加载归结为:

// Load initial state from server, convert it to Task instances, then populate self.tasks
$.getJSON("/tasks", function(allData) {
    var mappedTasks = $.map(allData, function(item) { return new Task(item) });
    self.tasks(mappedTasks);
}); 

Saving it to your service looks like this: 将其保存到您的服务看起来像这样:

self.save = function() {
    $.ajax("/tasks", {
        data: ko.toJSON({ tasks: self.tasks }),
        type: "post", contentType: "application/json",
        success: function(result) { alert(result) }
    });
};

A related second option is using the mapping plugin to save/load your ViewModels in a conventions-based way. 第二个相关选项是使用映射插件以基于约定的方式保存/加载ViewModel。 You still need some wiring to communicate with the server though. 但是,您仍然需要一些布线才能与服务器通信。

For the View part, in both cases I think you already had the correct approach: use a foreach binding on a tbody and construct one row per ViewModel. 对于View部分,在两种情况下,我都认为您已经采用了正确的方法:在tbody上使用foreach绑定 ,并为每个ViewModel构造一行。

Again, this is a pretty vague/broad answer, in part because your question is rather broad. 同样,这是一个相当模糊/广泛的答案,部分原因是您的问题很广泛。 Hope it helps. 希望能帮助到你。

This is the way to do it... I have made a jsfiddle showing this: 这是做到这一点的方法...我制作了一个jsfiddle显示如下:

To get this to work I had to add two callback methods to the original knockout foreach binding definition. 为了使它起作用,我必须在原始的敲除foreach绑定定义中添加两个回调方法。 I am currently trying to get these events into the newest version of knockout. 我目前正在尝试将这些事件纳入最新版本的淘汰赛中。 I needed to add a beforeRenderAll and afterRenderAll callback to destroy the datatable and reinitialize the datatable after the knockouts foreach binding adds the html. 我需要添加一个beforeRenderAll和afterRenderAll回调来销毁数据表,并在敲除foreach绑定添加html之后重新初始化数据表。 This works like a charm The JSFiddle showing this has a fully editable jquery datatable bound to the ViewModel through knockout. 这就像一个魅力。JSFiddle显示了它具有一个完全可编辑的jquery数据表,该数据表通过剔除绑定到ViewModel。

With Knockout, you wont be using the ajax implementation of datatables. 使用Knockout,您将不会使用数据表的Ajax实现。 You will be using the standard implementation where the html is already defined. 您将使用已定义html的标准实现。 Let Knockout handle the html by loading your data through ajax and assigning that to an observable array. 让Knockout通过ajax加载数据并将其分配给可观察数组来处理html。 The custom foreach binding below will then destroy the datatable, let knockout handle the html in the default knockout foreach fashion, and then the binding will reinitialize the datatable. 然后,下面的自定义foreach绑定将破坏数据表,让敲除以默认的敲除foreach方式处理html,然后绑定将重新初始化数据表。

var viewmodel = new function(){
   var self = this;
   this.Objects = ko.mapping.fromJS([]);
   this.GetObjects = function(){
       $.get('your api url here', function(data){
           ko.mapping.fromJS(
               data,
               {
                   key: function(o){ return ko.utils.unwrapObservable(o.Id); },
                   create: function(options){ return new YourObjectViewModel(options.data); }
               },
               that.Objects
           ); 
       });
   };
};

//Or if you do not need to map to a viewmodel simply just...
$.get('your api url here', function(data){
    viewmodel.Options(data);
});

And below is the custom datatables binding... 下面是自定义数据表绑定...

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