0

現在、Knockout には Josh Buckley の Datatables バインディングを使用しています。データテーブルに「行の削除」ボタンを作成しようとしています。現在、各ボタンにクリックデータバインドがあります。データテーブル ソースは、監視可能な配列に接続されています。ユーザーがボタンをクリックすると、オブザーバブル配列からオブジェクトが削除され、更新バインディングがトリガーされ、続いてテーブル ビューが更新されます。少なくともボタンを初めてクリックしたときは、すべて正常に機能します。

ただし、テーブルが更新されると、「行の削除」ボタンのすべてのクリック バインディングが機能しなくなります。これは、更新バインディングが呼び出されるたびにテーブル全体がクリアされて再構築されるため、バインディングが新しい要素に適用されないためだと思います。

データテーブルの更新ごとに生成される新しい要素を再バインドするにはどうすればよいですか? あるいは、これを処理するためのより良い方法はありますか?

カスタム バインディング:

(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/

Buckley の連中のデータ テーブル バインディングについてはよくわかりませんが、投稿した元のフィドルには多くの問題があるため、それらに触れて、投稿したソリューションが機能し、より良い方法である理由を確認できるようにします。

  1. データに何らかの機能 (削除やリンクなど) を与えるためだけに、配列の配列を作成しないでください。それは悪い習慣であり、問​​題に備えることになります。データ レコードに機能を追加するためにビューモデルに入れたような一般的なメソッドを使用するか、他の多数のメソッドを使用することができますが、ビュー モデルに HTML を追加しないでください。

  2. 機能を追加するために、ビュー モデルでデータを foreach する必要はありません。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 に答える