2012-01-06 15 views
9

私は、Knockout.jsを使っているプロジェクトでリスト項目をドラッグ可能にしようとしています。私は以下のコードを使用して、そしてあなたがそれを見ることができるようにすることは非常に簡単ですよノックアウト&JQueryUIドラッグ - この要素をドラッグできない原因は何ですか?

<div id="room-view" > 
    <ul data-bind="foreach: rooms">      
     <li data-bind="text: name" class="draggable room-shape"></li>     
    </ul>    
</div> 

<script type="text/javascript"> 
    $(function() { 
     $(".draggable").draggable(); 
    }); 
</script> 

の部屋 "のリストがうまくレンダリングしますが、項目のどれもドラッグ可能ではありません。しかし、ドラッグ可能なクラスをページの他の要素に適用すると、ドラッグ可能になります。それらが他のリスト項目であっても。唯一の違いは、これらのリスト項目が 'foreach'バインディングによって作成されていることです。

誰かがこれが正しく機能しない原因を見つけられますか?

答えて

23

foreach作品:

はこれを試してみてください。したがって、ドラッグ可能な要素は、foreachによってレンダリングされた要素ではありません。

draggableapplyBindingsの後に呼び出されるようにすることができますが、それはroomsが変更されるobservableArrayでない場合にのみ有効です。レンダリングされた新しいアイテムはドラッグできません。

もう1つの方法は、afterRenderオプションを使用して、あなたの要素にdraggableを呼び出すことです。

カスタムバインディングを使用することをお勧めします。

ko.bindingHandlers.draggable = { 
    init: function(element) { 
     $(element).draggable(); 
    } 
}; 

またはあなたが実際にあなたのアイテムがドロップされる場所に基づいてobservableArrayを更新少し良く何かに取得することができます:それはのような単純なものでした。

私は記事を書いた後にそれに戻ってhere。ノックアウト2.0では、バインディングを簡略化するためにいくつかの変更を加えました。そのため、親にsortableListを使用するだけです。ここで

だけでソート可能とサンプルです:ここではhttp://jsfiddle.net/rniemeyer/DVRVQ/

は、リスト間で落下したサンプルです:http://jsfiddle.net/rniemeyer/sBHaP/

+0

ああ、リスト間のサンプル抜き差しは驚くべきことです - 私が探しているものです。ありがとうございました! – PhillipKregg

+0

これは驚くほど単純で、依然として多くの制御を持っています。ありがとうございました! – Nek

+1

+1のjsfiddleの例 – Pieter

7

問題があるのは、の既存の要素のドキュメントが準備完了状態のときに適用されます。 Knockout.jsは、最初にHTMLを変更して新しい要素を作成し、rooms配列が更新されたときにも作成されます。

room-viewがレンダリングされるたびにドラッグを有効にする必要があります。そのためにafterRenderを使用することができます。それがアイテムをレンダリングする必要があるときに「テンプレート」として使用する要素のコピーをオフに保存することにより

<div id="room-view" > 
    <ul data-bind="foreach: { data: rooms, afterRender: afterRender }">      
    <li data-bind="text: name" class="draggable room-shape"></li>     
    </ul>    
</div> 

<script type="text/javascript"> 
    // this is your already existing view-model that contains rooms, etc 
    function roomsViewModel() { 
    // ... 

    // insert this in your view-model 
    this.afterRender = function() { 
     $(".draggable").draggable(); 
    } 
    } 

    ko.applyBindings(new roomsViewModel()); 
</script> 
+0

あなたの答えにも非常に便利である - 私は2つの答えをマークすることができたいと思います。 – PhillipKregg

+1

@PhillipKregg Hehe、ありがとうございました。ライアンの答えは素晴らしく、彼はKnockout.jsの有名人だから、彼は選ばれた人に値する。 – kubetz

+0

@dzejkejあまりにも良い答え! –

関連する問題