0

我目前正在为 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/

4

1 回答 1

0

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

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

  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 的依赖,因为您根本不需要它。

于 2013-07-22T03:15:55.820 回答