【问题标题】:Knockout + Datatables - update bindings in cells淘汰赛 + 数据表 - 更新单元格中的绑定
【发布时间】:2013-07-22 00:31:09
【问题描述】:

我目前正在为 Knockout 使用 Josh Buckley 的数据表绑定。我正在尝试在数据表中创建一个“删除行”按钮。我目前在每个按钮上都有一个点击数据绑定。数据表源连接到一个可观察的数组。当用户点击按钮时,对象会从 observable 数组中移除,然后触发更新绑定,表格视图随后会被更新。这一切都很好,至少在我第一次单击按钮时。

但是,一旦表格更新,“删除行”按钮上的所有点击绑定都将停止工作。我认为这是因为每次调用更新绑定时都会清除并重建整个表,因此绑定不会应用于新元素。

如何重新绑定每次更新数据表时生成的新元素?或者,有没有更好的方法来处理这个问题?

自定义绑定:

(function($){
    ko.bindingHandlers.dataTable = {
        init: function(element, valueAccessor){
            var binding = ko.utils.unwrapObservable(valueAccessor());

            // If the binding is an object with an options field,
            // initialise the dataTable with those options. 
            if(binding.options){
                $(element).dataTable(binding.options);
            }
        },
        update: function(element, valueAccessor){
            var binding = ko.utils.unwrapObservable(valueAccessor());

            // If the binding isn't an object, turn it into one. 
            if(!binding.data){
                binding = { data: valueAccessor() }
            }

            // Clear table
            $(element).dataTable().fnClearTable();

            // Rebuild table from data source specified in binding
            $(element).dataTable().fnAddData(binding.data());
        }
    };
})(jQuery);

HTML 代码:

<table id="membersTable" class="table table-striped table-bordered bootstrap-datatable datatable" data-bind="dataTable: membersTable">
    <thead>
        <tr>
            <th>Name</th>
            <th>Actions</th>
        </tr>
    </thead>   
</table>

查看模型:

var groupViewModel = {  
    groupMembers: ko.observableArray([
        new GroupMember("1", "Abe", true),
        new GroupMember("2", "Bob", false),
        new GroupMember("3", "Bill", false)
    ])
};

groupViewModel.membersTable = ko.computed(function() {
    var self = this;

    var final_array = new Array();
    for(var i = 0; i < self.groupMembers().length; i++)
    {
        var row_array = new Array();
        row_array[0] = self.groupMembers()[i].nameWithLink();
        row_array[1] = self.groupMembers()[i].actions();
        final_array.push(row_array);
    }

    return final_array;
}, groupViewModel);

groupViewModel.removeMember = function(id) {
    var self = this;

    self.groupMembers.remove(function(groupMember) {
        return groupMember.id == id;
    });
};

组成员对象:

function GroupMember(id, name, isGroupLeader)
{
    var self = this;
    self.id = id;
    self.name = name;
    self.isGroupLeader = ko.observable(isGroupLeader);

    self.link = ko.computed(function() {
        return "/#user/" + self.id;
    }); 

    self.nameWithLink = ko.computed(function() {
        return '<a href="' + self.link() + '">' + self.name + '</a>';
    });

    self.actions = ko.computed(function() {
        return '<a class="btn btn-danger" data-bind="click: function() {removeMember(' + self.id + ')}">' + '<i class="icon-minus-sign"></i>' + '</a>';
    });
}

编辑:

jsfiddle 链接:http://jsfiddle.net/zongweil/PLUKv/1/

【问题讨论】:

标签: knockout.js datatables


【解决方案1】:

http://jsfiddle.net/PLUKv/4/

我不确定 Buckley 伙计们的数据表绑定,但是您发布的原始小提琴中存在很多问题,因此我将讨论这些问题,以便您了解为什么我发布的解决方案有效并且是更好的方法 -

  1. 不要仅仅为了给你的数据一些功能(例如删除或链接)而创建一个数组数组。这是不好的做法,你正在为自己的问题做准备。您可以使用我在视图模型中添加的通用方法向数据记录添加功能,也可以使用大量其他方法 - 但不要在视图模型中添加 HTML。

  2. 您无需在视图模型中搜索数据即可添加功能。 Knockout 通过为您提供视图中所需的工具来帮助您,这样您的视图模型就不必对视图一无所知。另外,不要将视图模型功能放入您的视图中 - 这是不好的做法(您在 HTML 中注入了一个函数,这很脏!)

  3. 最后,不要将视图模型功能放入您的模型中——这就是您的视图模型的用途!

您的视图在渲染时更快、更高效 - 让它发挥作用 -

<tbody data-bind="foreach: groupMembers">
    <tr>
    <td><a data-bind="click: $parent.gotoPersonLink, text: name" /></td>
    <td><button data-bind="click: $parent.removeMember"><i class="icon-remove" /></button></td>
    </tr>
</tbody>

让您的视图模型有机会在无需注入 HTML 的情况下提供功能 -

self.removeMember = function (member) {
    self.groupMembers.remove(member);
};

self.gotoPersonLink = function (member) {
    alert('add your change window logic here');    
};

您始终可以在模型中添加功能,例如删除成员,但这意味着如果您有 1000 条记录,则代码运行次数比需要运行的次数多 999 次。话虽如此,如果您绝对必须回到原来的做法,那么祝您好运!如果是这种情况,请摆脱对 Knockout 的依赖,因为您根本不需要它。

【讨论】:

  • 感谢您的详细回复!我同意你的观点,在这种情况下它的结构有点奇怪,但那是因为数据表绑定只适用于数据源,而不适用于生成的行。我发布的代码是我自己的解决方法。您对可能修改绑定以使其可以使用生成的行有任何建议吗?我需要用于搜索/过滤/分页的数据表功能。
  • 另外,我很欣赏有关构建逻辑的技巧。几周前我拿起了 Knockout,所以我仍在努力学习最佳实践:)。
  • 好吧,在审查了一下之后,我知道可能有更好的方法来完成你想要完成的事情(将这些数据表与 Knockout 结合)但不幸的是,在审查了 Josh Buckley 没有的网站之后的小提琴正在运行并且进一步查看它似乎您的自定义绑定处理程序正在为每次更改重新生成表,这不利于让 Knockout 帮助您。您似乎缺少的唯一功能是过滤和分页 - 您是否看过像 Breeze.js 这样的库来处理这个问题?
  • 在环顾四周之后,我决定改用 KoGrid,所以我不必担心自定义绑定和所有这些混乱。感谢您的帮助!
猜你喜欢
  • 1970-01-01
  • 2014-10-30
  • 2017-05-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-18
  • 2013-12-30
  • 1970-01-01
相关资源
最近更新 更多