2011-09-05 12 views
9

sto lavorando su una pagina che è l'essere server da un'applicazione ASP.NET MVC3 che voglio usare KnockoutJS in.Collegamento knockoutjs a un elemento DOM già popolato

Sulla View Mi sto passato un populated Model (che sto convertendo in un viewModel KnockoutJS) e voglio costruire alcuni dei DOM lato server. Questo sembra logico dal momento che ho già gli oggetti lì per generare l'HTML iniziale e fornirà un'esperienza migliore agli utenti in quanto non ci sarà un ritardo tra il caricamento della pagina e la popolazione DOM (significa anche che ho funzionalità di base per non -JavaScript client).

Dopo aver fatto qualche ricerca sto assumendo Ho bisogno di creare un costume bindingHandler così ho creato questo:

ko.bindingHandlers.serverForEach = { 
    init: function() { /* no-op */ }, 
    update: function() { 
     //call off to the built in loop handler 
    } 
}; 

Quindi il mio pensiero era che creo un gestore, che non fa nulla nella fase init (come il DOM è già popolato) e nella fase update inserirò semplicemente il nuovo valore. Mi piacerebbe sfruttare il template integrato così questa può essere una soluzione generica.

Il problema è che tutto cade a pezzi in questo scenario. Se lo init non fa nulla, lo update fallisce poiché il bindingContext che arriva come ultimo argomento sembra sbagliato, e se includo l'init questo distruggerà l'HTML esistente.

Qualcuno ha provato questo/sa cosa dovrei fare per supportare questo scenario o è troppo lontano da ciò che è possibile/dovrebbe fare?

Inoltre, non desidero avere un elemento DOM separato per l'HTML generato dal server rispetto all'HTK knockout.

risposta

8

Penso di capire qual è il tuo problema. Si desidera compilare la markup inizialmente per utenti non js e semplicemente sovrascriverla durante il binding a KO.

Per collegamenti semplici come il testo questo non è un problema, basta includere l'attributo data-bind nel markup dal server o includere in runtime e via. Per il modello foreach le cose vincolanti sono un po 'più difficili dato che aggiungerà dei valori quando vincolati.

Here is a jsfiddle che descrive lo scenario precedente e dimostra la soluzione seguente. È un po 'di base, ma dovrebbe iniziare.

L'idea di base è cancellare l'elemento su init e quindi delegare il resto al binding del modello esistente.

ko.bindingHandlers.serverForEach = { 
    init: function(element, valueAccessor, allBindingsAccessor, viewModel) { 
     // clear the list first 
     $(element).children().remove(); 
    }, 
    update: function(element, valueAccessor, allBindingsAccessor, viewModel) { 
     ko.bindingHandlers['template'].update(element, valueAccessor, allBindingsAccessor, viewModel); 
    } 
}; 

Spero che questo aiuti.

2

Se occorre far funzionare per knockout.js 2.0 + (notare il bindingContext in aggiornamento)

ko.bindingHandlers.serverForEach = { 
init: function(element, valueAccessor) { 
     $(element).children().remove(); 
     return ko.bindingHandlers.template.init(element, valueAccessor); 
    }, 
    update: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) { 
     return ko.bindingHandlers.template.update(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext); 
    } 
}; 
Problemi correlati