2014-10-07 11 views
25

afterRender funziona con i collegamenti dei modelli, ma dopo aver convertito i miei modelli in componenti, non sembra esserci alcun modo di utilizzare afterRender. Ho provato a cercare un esempio di un componente che utilizza afterRender, ma non riesce a trovare nulla.AfterRender funziona con i componenti Knockout?

+0

si prega di fornire fonte, magari in un JSFiddle –

+0

Guardando alla fonte, non sembra come lo fa. Non utilizza il motore di template per il rendering dei componenti, ma semplicemente applica il modello del componente al template del componente. –

+0

OK, non sono sorpreso, i componenti sono piuttosto nuovi, in quanto ho dovuto eseguire l'aggiornamento all'ultima versione di Knockout per farli funzionare. Mi sembra di dover capire come funziona createViewModel (params, componentInfo). –

risposta

7

Il segreto qui è http://knockoutjs.com/documentation/custom-bindings.html

ko.bindingHandlers.myCustomBinding = { 
    init: function(element, valueAccessor, allBindings, viewModel, bindingContext) { 
    // This will be called when the binding is first applied to an element 
    // Set up any initial state, event handlers, etc. here 
    if (bindingContext.$data.init) bindingContext.$data.init(element, valueAccessor, allBindings, viewModel, bindingContext); 
    }, 
    update: function(element, valueAccessor, allBindings, viewModel, bindingContext) { 
    // This will be called once when the binding is first applied to an element, 
    // and again whenever any observables/computeds that are accessed change 
    // Update the DOM element based on the supplied values here. 
    if (bindingContext.$data.update) bindingContext.$data.update(element, valueAccessor, allBindings, viewModel, bindingContext); 
    } 
}; 

così nel mio modello componente I fare qualcosa di simile

<div class="row-fluid" data-bind="myCustomBinding: 'someValue'"> 

e sul ViewModel componente ho appena implementare init e/o aggiornamento, ad esempio:

constructor.prototype.init = function(element, valueAccessor, allBindings, viewModel, bindingContext) { 
    // All the buttons in the buttons group need the same name, 
    // but they all need distinct ids. We use timestamps because 
    // as components, the names and ids should be distinct across 
    // multiple instances of each component. 
    var timeStamp = new Date().getTime(); 
    $('input:radio').attr('name', timeStamp).button(); 
    $('input:radio:eq(0)').attr('id', timeStamp+1); 
    $('input:radio:eq(1)').attr('id', timeStamp+2); 
    $('input:radio:eq(2)').attr('id', timeStamp+3); 

    // Initialize the number-picker 
    $('input[name="number-picker"]').TouchSpin(); 
}; 

La documentazione di Knockout potrebbe essere migliorata indicando t il suo caso molto utile. Inoltre, questo è un utile vincolante tale, non dovrebbe essere un binding standard per 'init' e 'aggiornamento', ad esempio

<div data-bind="init: 'someValue'"> 
+0

Ciao, ho provato ad usarlo ma non sono riuscito a farlo funzionare. Riesco a vedere il codice in esecuzione ma semplicemente non influenza gli elementi dom ... quindi non riesco ad ottenere un selettore di numeri telefonici da eseguire :( –

+0

Ho trovato un metodo alternativo che funziona Vedi il mio post qui sotto –

33

non ho potuto ottenere il metodo di lavoro di cui al post sopra. Tuttavia ho trovato una soluzione alternativa alla lista dei problemi di git e non richiede un binding KO personalizzato.

Aggiungere la riga sottostante nel modello componente html o stringa di codice.

<span data-bind="template: { afterRender: init }"></span> 

quindi creare una funzione init nel vostro modulo/ViewModel:

this.init = function() { 
    Do cool DOM stuff here. 
} 

o in base alla struttura del ViewModel:

viewModel: function(params) { 
    return { 
     init: function() { 

     } 
    }; 
}, 

funziona come un fascino. Esempio di esso di lavoro è qui

http://jsfiddle.net/gLcfxkv6/1/

Discussione sul knockout git qui: https://github.com/knockout/knockout/issues/1533

Grazie a vampiri su git per la soluzione.

+0

Grazie ... Funziona per ora ... sembra che Knockout lo aggiungerà come funzione nella v3.3 –

+3

Basta fare attenzione a fare in modo che i componenti annidati non chiamino dopoRender come previsto. –

+0

Grazie ... nel mio caso d'uso, volevo solo eseguire un processo dopo il il componente più in alto è stato fatto. –

6

Avevamo bisogno di accedere agli elementi DOM in un componente dopo il passaggio tra diversi componenti. Ci sarebbe piaciuto utilizzare l'associazione "afterRender" non esistente sui componenti.

L'abbiamo risolto con un setTimeout di Javascript, lasciando che KO eseguisse il rendering per primo e in effetti mettesse in coda il nostro codice.

HTML:

<div data-bind="component: compName"></div> 

Il codice di commutazione della componente:

var compName = ko.observable(); 

//... 

compName(switchToComponent); 
setTimeout(function(){ 
    // this code is queued until after the component is rendered. 
}, 0); 
+0

Trucchetto pulito, non lo sapevo! –

Problemi correlati