2014-10-07 5 views
25

afterRender funktioniert mit Vorlagenbindungen, aber nach dem Konvertieren meiner Vorlagen in Komponenten scheint es keine Möglichkeit zu geben, afterRender zu verwenden. Ich habe versucht, nach einem Beispiel für eine Komponente zu suchen, die afterRender verwendet, aber nichts finden kann.Funktioniert AfterRender mit Knockout-Komponenten?

+0

bitte Quelle bieten, vielleicht in einem JSFiddle –

+0

an der Quelle der Suche, es nicht aussehen, wie es der Fall ist. Es verwendet die Vorlagen-Engine nicht zum Rendern der Komponenten, sondern wendet lediglich das Komponentenmodell auf die Komponentenvorlage an. –

+0

OK, ich bin nicht überrascht, Komponenten sind ziemlich neu, da ich auf die neueste Version von Knockout upgraden musste, um sie zur Arbeit zu bringen. Ich sehe aus wie ich muss verstehen, wie createViewModel (params, componentInfo) funktioniert. –

Antwort

7

Das Geheimnis hier ist 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); 
    } 
}; 

so in meiner Komponentenvorlage ich, wie etwas zu tun

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

und auf der Komponente Ansichtsmodell I implementieren nur init und/oder zu aktualisieren, zum Beispiel:

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(); 
}; 

Die Knockout-Dokumentation könnte verbessert werden, indem man auf t sein sehr nützlicher Fall. Auch dies ist eine solche nützliche Bindung, sollte es eine Standard-Bindings für ‚init‘ und ‚update‘, zum Beispiel

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

Hallo, ich habe versucht, dies zu benutzen, aber ich konnte es nicht funktionieren. Ich kann sehen, dass der Code ausgeführt wird, aber es wirkt sich nicht auf die Dom-Elemente aus ... so kann ich beispielsweise keine Telefonnummernauswahl ausführen :( –

+0

Ich habe eine alternative Methode gefunden, die funktioniert. Siehe meinen Beitrag unten. –

33

ich nicht Durchführung des Verfahrens gemäß dem oben genannten Post bekommen konnte. Allerdings habe ich einen Workaround in der Git-Problemliste gefunden und es benötigt keine benutzerdefinierte KO-Bindung.

Fügen Sie die folgende Zeile in Ihrer Komponentenvorlage html oder Zeichenfolge ein.

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

Dann eine init-Funktion in Ihrem Modul/Ansichtsmodell erstellen:

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

oder je nach Ansichtsmodell Struktur:

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

     } 
    }; 
}, 

Arbeiten wie ein Charme. Beispiel dafür arbeiten, ist hier

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

Thema auf Knockout git hier: https://github.com/knockout/knockout/issues/1533

Dank Vamps auf git für die Problemumgehung.

+0

Danke ... Dies funktioniert für jetzt ... sieht aus wie Knockout wird dies als ein Feature in v3.3 hinzufügen –

+3

Seien Sie vorsichtig, verschachtelte Komponenten rufen Sie nicht nachRender wie erwartet –

+0

Danke ... in meinem Anwendungsfall, wollte ich nur einen Prozess nach dem laufen Top-Komponente wurde gemacht –

6

Wir mussten nach dem Umschalten zwischen verschiedenen Komponenten auf DOM-Elemente in einer Komponente zugreifen. Wir hätten gerne die nicht vorhandene Bindung "afterRender" für Komponenten verwendet.

Wir haben es mit einem Javascript setTimeout gelöst, damit KO zuerst das Rendering durchführen kann und wir den Code danach in die Warteschlange stellen.

HTML:

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

Der Code Umschalten der Komponente:

var compName = ko.observable(); 

//... 

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

Ordentlicher Trick, wusste das nicht! –