Können Sie ko.applyBindings aufrufen, um eine Teilansicht zu binden?

257

Ich verwende KnockoutJS und habe eine Hauptansicht und ein Ansichtsmodell. Ich möchte, dass ein Dialogfeld (das jQuery-UI) mit einer anderen Ansicht angezeigt wird, an die ein separates untergeordnetes Ansichtsmodell gebunden werden soll.

Der HTML-Code für den Dialoginhalt wird mit AJAX abgerufen, sodass ich nach Abschluss ko.applyBindingsder Anforderung aufrufen und das untergeordnete Ansichtsmodell nur an den Teil des HTML-Codes binden möchte, der über Ajax im Dialogfeld div geladen wurde.

Ist dies tatsächlich möglich oder muss ich ALLE meine Ansichten und Ansichtsmodelle laden, wenn die Seite zum ersten Mal geladen und dann ko.applyBindingseinmal aufgerufen wird?

Charlie
quelle

Antworten:

430

ko.applyBindings Akzeptiert einen zweiten Parameter, der ein DOM-Element ist, das als Root verwendet werden soll.

So können Sie Folgendes tun:

<div id="one">
  <input data-bind="value: name" />
</div>

<div id="two">
  <input data-bind="value: name" />
</div>

<script type="text/javascript">
  var viewModelA = {
     name: ko.observable("Bob")
  };

  var viewModelB = {
     name: ko.observable("Ted")
  };

  ko.applyBindings(viewModelA, document.getElementById("one"));
  ko.applyBindings(viewModelB, document.getElementById("two"));
</script>

Mit dieser Technik können Sie also ein viewModel an den dynamischen Inhalt binden, den Sie in Ihren Dialog laden. Insgesamt sollten Sie nur darauf achten, dass Sie nicht applyBindingsmehrmals dieselben Elemente aufrufen , da mehrere Ereignishandler angehängt werden.

RP Niemeyer
quelle
17
Wenn Sie auch Bindungen später entfernen möchten, können Sie entweder anrufen, ko.cleanNode(document.getElementById("one")um Dinge zu bereinigen, oder ko.removeNode(document.getElementById("one")um Dinge zu bereinigen und den Knoten aus dem DOM zu entfernen.
Michael Berkompas
7
Nur ein Hinweis , dass cleanNodeund removeNodenicht Event - Handler entfernen, so etwas Vorsicht walten lassen. In einigen Fällen ist es vorzuziehen, die templateoder die withBindung für diese Bereiche zu verwenden, damit neue Elemente gerendert werden.
RP Niemeyer
7
Es ist derzeit etwas, was in KO fehlt. Wir beabsichtigen nicht speziell, dass Personen Abschnitte "neu binden". KO hängt jedoch Ereignisse mit jQuery an, wenn darauf verwiesen wird, sodass Sie $(element).unbind();alle Handler entfernen können.
RP Niemeyer
5
Wo sind diese Funktionen (applyBindings, cleanNode, removeNode) dokumentiert? Ich kann ihre Funktionssignaturen nicht auf knockoutjs.com finden.
EricP
2
Wäre schön, wenn dies irgendwo in der Dokumentation leicht zu finden wäre. Ich habe nicht einmal eine Erwähnung davon gesehen.
Travis Kaufman
61

Während Niemeyer Antwort eine richtige Antwort auf die Frage ist, Sie könnten auch Folgendes tun:

<div>
  <input data-bind="value: VMA.name" />
</div>

<div>
  <input data-bind="value: VMB.name" />
</div>

<script type="text/javascript">
  var viewModels = {
     VMA: {name: ko.observable("Bob")},
     VMB: {name: ko.observable("Ted")}
  };

  ko.applyBindings(viewModels);
</script>

Dies bedeutet, dass Sie das DOM-Element nicht angeben müssen und sogar mehrere Modelle wie folgt an dasselbe Element binden können:

<div>
  <input data-bind="value: VMA.name() + ' and ' + VMB.name()" />
</div>
mhu
quelle
4
Sie können auch "with" verwenden, um Regionen der Seite einzelnen Modellen zuzuweisen - data-bind = "with: VMA"
lexicalscope
3
@ Flamingpenguin: Ja, aber withnicht billig, siehe: Link
mhu
7

Ich habe es geschafft, ein benutzerdefiniertes Modell zur Laufzeit an ein Element zu binden. Der Code ist hier: http://jsfiddle.net/ZiglioNZ/tzD4T/457/

Das Interessante ist, dass ich das Datenbindungsattribut auf ein Element anwende, das ich nicht definiert habe:

    var handle = slider.slider().find(".ui-slider-handle").first();
    $(handle).attr("data-bind", "tooltip: viewModel.value");
    ko.applyBindings(viewModel.value, $(handle)[0]);
ZiglioUK
quelle
Bei Problemen mit ko 2.3 befindet sich der obige Code in einem Kundenhandler, der aufgerufen wird, wenn ich das globale ko.applyBindings () anwende. Jetzt erhalte ich die Fehlermeldung "Sie können Bindungen nicht mehrmals auf dasselbe Element anwenden." Ich versuche immer noch herauszufinden, warum ich den Fehler bekomme. Können wir nicht mehrmals eine Bindung auf dieselbe Variable anwenden, jeweils auf verschiedene Elemente?
ZiglioUK
Hier ist die Version mit ko 2.3, die nicht funktioniert: jsfiddle.net/ZiglioNZ/tzD4T/458
ZiglioUK
Das Hinzufügen eines Aufrufs von ko.cleanNode () vor dem Aufruf von applyBinding zur Teilansicht scheint nicht zu helfen: jsfiddle.net/ZiglioNZ/tzD4T/459
ZiglioUK
Gelöst: Ich musste nicht einmal applyBindings aufrufen!
ZiglioUK
Ich habe gerade den Knockoutjs-Quellcode bearbeitet und den Teil kommentiert, in dem die Funktion "Sie können Bindungen nicht mehrmals auf dasselbe Element anwenden.", jetzt funktioniert alles in Ordnung. Ich weiß, dass dies eine schmutzige Lösung ist, aber ich bin neu in der Bibliothek Ich weiß nicht, wie ich es nicht mehrmals für mein Problem anwenden soll.
Geomorillo