2012-01-06 2 views
9

Sto cercando di rendere trascinabile una voce di elenco in un progetto che utilizza Knockout.js.Knockout & JQueryUI Trascinare: cosa sta causando l'impossibilità di trascinare questo elemento?

sto usando il codice qui sotto, e come potete vedere, è molto semplice:

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

L'elenco dei 'stanza' rende bene, ma nessuno degli articoli sono trascinabili. Tuttavia, se applico la classe 'trascinabile' a qualsiasi altro elemento della pagina, diventa trascinabile. Anche se sono altri elementi della lista. L'unica differenza è che questi elementi di elenco vengono creati tramite l'associazione "foreach".

Qualcuno può individuare ciò che potrebbe causarne il malfunzionamento?

risposta

23

foreach opere salvando fuori una copia degli elementi da utilizzare come "modello" ogni volta che ha bisogno di rendere un elemento. Quindi, gli elementi che hai reso trascinabili non sono quelli che sono stati renderizzati da foreach.

Si può provare ad assicurarsi che draggable venga chiamato dopo applyBindings, ma che sarebbe efficace solo se il tuo rooms non è un array osservabile che cambia. Qualsiasi nuovo articolo reso non sarebbe trascinabile.

Un'altra opzione consiste nell'utilizzare l'opzione afterRender per chiamare draggable sui propri elementi.

Un modo migliore è utilizzare un'associazione personalizzata. Potrebbe essere semplice come:

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

oppure si può entrare in qualcosa di un po 'meglio dove realmente aggiorna un observableArray in base a dove vengono eliminati i tuoi oggetti.

Ho scritto un articolo su di esso here. Con Knockout 2.0, ho apportato alcune modifiche per semplificare l'associazione in modo da poter utilizzare semplicemente sortableList sul genitore.

Ecco un esempio con un solo ordinabile: http://jsfiddle.net/rniemeyer/DVRVQ/

Ecco un esempio a cadere tra le liste: http://jsfiddle.net/rniemeyer/sBHaP/

+0

Ahhh, il campionamento tra gli elenchi è incredibile - esattamente quello che sto cercando. Grazie! – PhillipKregg

+0

Questo è incredibilmente semplice e ha ancora molto controllo. Grazie! – Nek

+1

+1 per esempi jsfiddle – Pieter

7

Il problema è che draggable() viene applicato quando il documento è pronto su elementi esistenti. Knockout.js modificherà l'HTML e creerà nuovi elementi all'inizio e anche quando l'array rooms viene aggiornato.

Ciò che è necessario abilitare il trascinamento ogni volta che viene eseguito il rendering di room-view. È possibile utilizzare afterRender per quello.

Prova questo:

<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

la vostra risposta è anche estremamente utile - vorrei poter segnare 2 risposte. – PhillipKregg

+1

@PhillipKregg Hehe, grazie :). La risposta di Ryan è grandiosa e lui è una celebrità di Knockout.js, quindi merita di essere il prescelto: P. – kubetz

+0

@dzejkej buona risposta anche! –