2012-01-22 12 views
1

私はクエリーとノックアウトを使用してweb-abbを構築しています。 特定のページには、いくつかの項目のリストがあります。 これらのリストは並べ替え可能で接続されているので、JQueryがすべて機能している限りOKです。 Ryan Niemeyerの例を使用して、ソート可能オブジェクトのカスタムバインドを作成し、ビューモデルの観測可能な配列を更新しました。ノックアウト観測配列間のアイテムの移動を検出する方法

これはすべてうまく動作しますが、変更をバックエンドサーバーに保存します。 観測可能な配列でサブスクリプションを使用すると、アイテムが削除されて配列に追加されたことを検出できますが、これによってバックエンドサーバーへの更新が2回呼び出されます。

これらの呼び出し中に問題が発生すると、バックエンドは無効な状態になります。

アイテムの削除とその後の同じアイテムの追加を検出して、Webアプリケーションがバックエンドサーバーに対して1回の移動呼び出しを行うことができるようになるにはどうすればよいでしょうか?

答えて

3

これを処理する良い方法は、item、元の親、新しい親を引数として渡すsortableListバインディングにコールバックオプションを追加することだと思います。ここで

は私がKO 2.0のために使用していることをバインディングがコールバックでどのように見えるかです:

//connect items with observableArrays 
ko.bindingHandlers.sortableList = { 
    init: function(element, valueAccessor, allBindingsAccessor, data, context) { 
     var options = ko.utils.unwrapObservable(valueAccessor()); 

     //attach the appropriate class to our element 
     if (ko.bindingHandlers.sortableList.autoAddClass) { 
      ko.utils.toggleDomNodeCssClass(element, ko.bindingHandlers.sortableList.defaultClass, true); 
     } 

     $(element).data("sortList", options.list || valueAccessor()); //attach meta-data 
     $(element).sortable({ 
      update: function(event, ui) { 
       var item = ui.item.data("sortItem"); 
       if (item) { 
        //identify parents 
        var originalParent = ui.item.data("parentList"); 
        var newParent = ui.item.parent().data("sortList"); 
        //figure out its new position 
        var position = ko.utils.arrayIndexOf(ui.item.parent().children(), ui.item[0]); 
        if (position >= 0) { 
         originalParent.remove(item); 
         newParent.splice(position, 0, item); 
        } 
        ui.item.remove(); 

        if (options.afterDrop) { 
         options.afterDrop.call(this, item, newParent, originalParent); 
        } 
       } 
      }, 
      connectWith: '.' + ko.bindingHandlers.sortableList.defaultClass 
     }); 
     return ko.bindingHandlers.template.init.apply(this, arguments); 
    }, 
    update: function(element, valueAccessor, allBindingsAccessor, data, context) { 
     var options = ko.utils.unwrapObservable(valueAccessor()), 
      newOptions = {}; 

     //build our options to pass to the template engine 
     if (options.list) { 
      newOptions.foreach = options.list; 
      newOptions.name = options.tmpl; 
      newOptions.includeDestroyed = options.includeDestroyed; 
      newOptions.afterAdd = options.afterAdd; 
      newOptions.beforeRemove = options.beforeRemove; 
     } else { 
      newOptions.foreach = valueAccessor(); 
     } 

     //use an afterRender function to add meta-data 
     if (options.afterRender) { 
      //wrap the existing function, if it was passed 
      newOptions.afterRender = function(element, data) { 
       ko.bindingHandlers.sortableList.afterRender.call(data, element, data); 
       options.afterRender.call(data, element, data); 
      } 
     } else { 
      newOptions.afterRender = ko.bindingHandlers.sortableList.afterRender; 
     } 
     //call the actual template binding 
     ko.bindingHandlers.template.update(element, function() { return newOptions; }, allBindingsAccessor, data, context); 
    }, 
    afterRender: function(elements, data) { 
     ko.utils.arrayForEach(elements, function(element) { 
      if (element.nodeType === 1) { 
       $(element).data("sortItem", data); 
       $(element).data("parentList", $(element).parent().data("sortList")); 
      } 
     }); 
    }, 
    defaultClass: 'container', 
    autoAddClass: true 
}; 

あなたは、その後のようなバインディングを指定します:今

<ul data-bind="sortableList: { tmpl: 'myItems', list: myObservableArray, afterDrop: myCallback }"></ul> 

、あなたが追加することができますそのアイテムが移動されたことをサーバーに伝える独自のコールバック。 observableArraysは関数(オブジェクト)なので、実際にプロパティを割り当てることができます。ここで私は、各観察可能な配列にidプロパティを割り当てられたサンプルがあると私は古い親だったものと新しい親だったかを知るに優しい方法があるように、その後、コールバックでアクセス:

http://jsfiddle.net/rniemeyer/QZscP/

+0

あなたの例を使用して、Thanx Ryanは私に似たものを実装しました。私のアプリではアイテムが追加または削除される理由は複数ある可能性があるため、いくつかの追加機能が必要でした。 Btw、ノックアウトについてのあなたの記事は本当に素晴らしいです、私はそれらを頻繁に使用する!私は彼らがなければノックアウトを使用すると思うしないでください。 – RogierBessem

+0

@RogierBessem最近私はこれを少しきれいにして、ここでプロジェクトを作成しました:https://github.com/rniemeyer/knockout-sortable。たぶん新しいバージョンがあなたのために働くかもしれないし、フィードバックを自由に共有することができれば確かです。ありがとう! –

関連する問題