Pouvez-vous appeler ko.applyBindings pour lier une vue partielle?

258

J'utilise KnockoutJS et j'ai une vue principale et un modèle de vue. Je veux qu'une boîte de dialogue (celle de jQuery UI) s'affiche avec une autre vue à laquelle un modèle de vue enfant distinct doit être lié.

Le code HTML du contenu de la boîte de dialogue est récupéré à l'aide d'AJAX, je veux donc pouvoir appeler ko.applyBindingsune fois la demande terminée et je veux lier le modèle de vue enfant à la partie du code HTML chargée via ajax dans la boîte de dialogue div.

Est-ce réellement possible ou dois-je charger TOUTES mes vues et modèles de vues lors du chargement initial de la page, puis appeler ko.applyBindingsune fois?

Charlie
la source

Réponses:

431

ko.applyBindings accepte un deuxième paramètre qui est un élément DOM à utiliser comme racine.

Cela vous permettrait de faire quelque chose comme:

<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>

Ainsi, vous pouvez utiliser cette technique pour lier un viewModel au contenu dynamique que vous chargez dans votre boîte de dialogue. Dans l'ensemble, vous voulez juste faire attention à ne pas appeler applyBindingsplusieurs fois sur les mêmes éléments, car vous aurez plusieurs gestionnaires d'événements attachés.

RP Niemeyer
la source
17
Si vous souhaitez également supprimer les liaisons à un moment donné, vous pouvez appeler soit ko.cleanNode(document.getElementById("one")pour nettoyer les choses, soit ko.removeNode(document.getElementById("one")pour nettoyer les choses et supprimer le nœud du DOM.
Michael Berkompas
7
Juste une note cleanNodeet removeNodene supprimera pas les gestionnaires d'événements, utilisez donc une certaine prudence. Dans certains cas, il est préférable d'utiliser le templateou la withliaison sur ces zones, afin que de nouveaux éléments soient rendus.
RP Niemeyer
7
C'est actuellement quelque chose qui manque à KO. Nous n'avons pas spécifiquement l'intention de "relier" les sections. Cependant, KO attache des événements à l'aide de jQuery, s'il est référencé, vous pouvez $(element).unbind();donc supprimer tous les gestionnaires.
RP Niemeyer
5
Où ces fonctions (applyBindings, cleanNode, removeNode) sont-elles documentées? Je ne trouve pas leurs signatures de fonction sur knockoutjs.com.
EricP
2
Ce serait bien si c'était quelque part facilement localisable dans la documentation. Je n'en ai même pas vu mention.
Travis Kaufman
61

Bien que la réponse de Niemeyer soit une réponse plus correcte à la question, vous pouvez également faire ce qui suit:

<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>

Cela signifie que vous n'avez pas besoin de spécifier l'élément DOM, et vous pouvez même lier plusieurs modèles au même élément, comme ceci:

<div>
  <input data-bind="value: VMA.name() + ' and ' + VMB.name()" />
</div>
mhu
la source
4
vous pouvez également utiliser "avec" pour allouer des régions de la page à des modèles individuels - data-bind = "avec: VMA"
lexicalscope
3
@flamingpenguin: Oui, mais ce withn'est pas bon marché, voir: link
mhu
7

J'ai réussi à lier un modèle personnalisé à un élément lors de l'exécution. Le code est ici: http://jsfiddle.net/ZiglioNZ/tzD4T/457/

Le bit intéressant est que j'applique l'attribut data-bind à un élément que je n'ai pas défini:

    var handle = slider.slider().find(".ui-slider-handle").first();
    $(handle).attr("data-bind", "tooltip: viewModel.value");
    ko.applyBindings(viewModel.value, $(handle)[0]);
ZiglioUK
la source
ayant des problèmes avec ko 2.3, le code ci-dessus est dans un gestionnaire client qui est appelé lorsque j'applique le ko.applyBindings () global. Alors maintenant, je reçois l'erreur "Vous ne pouvez pas appliquer plusieurs fois des liaisons au même élément.". J'essaie toujours de comprendre pourquoi j'obtiens l'erreur. Ne pouvons-nous pas appliquer une liaison à la même variable plusieurs fois, chacune à des éléments différents?
ZiglioUK
Voici la version avec ko 2.3 qui ne fonctionne pas: jsfiddle.net/ZiglioNZ/tzD4T/458
ZiglioUK
Ajouter un appel à ko.cleanNode () avant d'appeler applyBinding à la vue partielle ne semble pas aider: jsfiddle.net/ZiglioNZ/tzD4T/459
ZiglioUK
Résolu: je n'avais même pas besoin d'appeler applyBindings!
ZiglioUK
ive vient de modifier le code source de knockoutjs et a commenté la partie où la fonction twrows "Vous ne pouvez pas appliquer des liaisons plusieurs fois au même élément.", maintenant tout fonctionne bien ... je sais que c'est une solution sale mais je suis nouveau dans la bibliothèque donc je ne sais pas comment ne pas l'appliquer plusieurs fois pour mon problème.
Geomorillo