2012-03-01 14 views
7

Ho una breve domanda su customBindings, si spera che qualcuno possa aiutarmi a spiegarmi? Ho pensato che quando un osservabile viene aggiornato che qualsiasi customBinding associato a tale osservabile dovrebbe avere il suo metodo di "aggiornamento" chiamato. Riesco a vedere che quando aggiorno il mio osservabile, gli altri abbonati vengono avvisati, ma non sembra che si stia chiamando CustomBinding.Knockout + customBinding not updating

Ecco il mio ViewModel:

var innerModel = { 
    name: ko.observable('junk') 
}; 

var innerModel2 = { 
    name: ko.observable('junk2') 
}; 

var viewModel = { 
    im1: innerModel, 
    im2: innerModel2, 
    selectedModel: ko.observable({name:'xxx'}) 
}; 

e qui è la mia customBinding:

ko.bindingHandlers.custom = { 
    update: function(element, valueAccessor) { 
     console.log("BAM!"); 
     while (element.firstChild) 
      ko.removeNode(element.firstChild); 

     ko.renderTemplate('test', valueAccessor(), {}, element, 'replaceNode'); 

    } 
}; 

dove il mio modello è semplicemente un arco che visualizza il campo "Nome":

<script id='test' type='text/html' charset='utf-8'> 
<span data-bind='text: name'></span> 
</script> 

Ecco l'HTML che utilizzo con CustomBinding:

<div id="container" data-bind="with: viewModel"> 
    <div data-bind="custom: selectedModel"> 
    </div> 
</div> 

Quando aggiorno selectedModel in uno dei due innerModels, viene visualizzato il nome corretto ma la funzione di 'aggiornamento' di CustomBinding non viene chiamata. Ho un abbonato separato per il "selectedModel" osservabile:

viewModel.selectedModel.subscribe(function(newValue) { 
    console.log(newValue.name()); 
}); 

e che si chiama quando cambio la selectedModel, quindi perché non è l'aggiornamento del customBinding essere chiamato?

Ecco un jsfiddle che mostra il problema: http://jsfiddle.net/gperng/twAcJ/

Qualsiasi aiuto sarebbe apprezzato!

risposta

0

L'utilizzo di with in questo caso è errato. Se si utilizza questo, funzionerà come ci si aspetta:

<div id="container" data-bind="with: selectedModel"> 
    <div data-bind="custom: $data"> 
    </div> 
</div> 

Questo perché nel tuo esempio il custom vincolante non è sul selectedModel, ma su tutta la stessa ViewModel che non cambia.

Ecco il jsfiddle di esso: http://jsfiddle.net/soniiic/twAcJ/7/

+1

io non sono al 100% ciò ha senso. Se tolgo il div con il binding "with", ricorro sempre allo stesso problema di prima (in cui il gestore dell'aggiornamento del binding personalizzato non viene chiamato nonostante venga modificato l'osservabile). Inoltre, nel tuo esempio, il "init" del binding personalizzato viene chiamato ogni volta (poiché il genitore con è l'osservabile e modificato, quindi tutti gli elementi figli sottostanti vengono resi nuovamente). Vedi http://jsfiddle.net/gperng/6nw8B/, ho aggiunto una funzione "init" e puoi vedere che l'associazione viene reinizializzata ogni volta. –

9

È necessario chiamare la seguente funzione per farlo funzionare:

var valueUnwrapped = ko.utils.unwrapObservable(valueAccessor()) 

Prova questo violino per più: http://jsfiddle.net/twAcJ/13/

+0

Questo in realtà non funziona per me. Stampa solo "BAM!" una volta, sempre. Nonostante abbia premuto tutti i pulsanti più volte. Si noti che ho selezionato la versione 3.0.0 (anche se la 2.3.0 non ha funzionato). – Aktau