¿Se puede llamar a ko.applyBindings para vincular una vista parcial?

258

Estoy usando KnockoutJS y tengo una vista principal y un modelo de vista. Quiero que aparezca un cuadro de diálogo (el de jQuery UI) con otra vista a la que se vinculará un modelo de vista secundaria independiente.

El HTML para el contenido del cuadro de diálogo se recupera usando AJAX, por lo que quiero poder llamar ko.applyBindingsuna vez que se haya completado la solicitud, y quiero vincular el modelo de vista secundaria a solo la parte del HTML cargado a través de ajax dentro del cuadro de diálogo div.

¿Es esto realmente posible o necesito cargar TODAS mis vistas y ver modelos cuando la página se carga inicialmente y luego llamar ko.applyBindingsuna vez?

Charlie
fuente

Respuestas:

431

ko.applyBindings acepta un segundo parámetro que es un elemento DOM para usar como raíz.

Esto te permitiría hacer algo como:

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

Por lo tanto, puede utilizar esta técnica para vincular un modelo de vista al contenido dinámico que carga en su cuadro de diálogo. En general, solo debe tener cuidado de no llamar applyBindingsvarias veces a los mismos elementos, ya que obtendrá varios controladores de eventos adjuntos.

RP Niemeyer
fuente
17
Si también desea eliminar enlaces en algún momento en el camino, puede llamar ko.cleanNode(document.getElementById("one")para limpiar cosas o ko.removeNode(document.getElementById("one")para limpiar y eliminar el nodo del DOM.
Michael Berkompas
77
Sólo una nota que cleanNodey removeNodeno eliminará los controladores de eventos, a fin de utilizar cierta cautela. En algunos casos, es preferible utilizar el templateo withvinculante sobre esas zonas, por lo que tiene nuevos elementos prestados.
RP Niemeyer
77
Actualmente es algo que falta en KO. No tenemos la intención específica de que las personas "vuelvan a unir" secciones. Sin embargo, KO adjunta eventos usando jQuery, si se hace referencia, por lo que puede hacer $(element).unbind();para eliminar todos los controladores.
RP Niemeyer
55
¿Dónde se documentan estas funciones (applyBindings, cleanNode, removeNode)? No puedo encontrar sus firmas de funciones en knockoutjs.com.
EricP
2
Sería bueno si este fuera un lugar fácilmente localizable dentro de la documentación. Ni siquiera vi una mención al respecto.
Travis Kaufman
61

Si bien la respuesta de Niemeyer es una respuesta más correcta a la pregunta, también puede hacer lo siguiente:

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

Esto significa que no tiene que especificar el elemento DOM, e incluso puede vincular varios modelos al mismo elemento, de esta manera:

<div>
  <input data-bind="value: VMA.name() + ' and ' + VMB.name()" />
</div>
mhu
fuente
44
también puede usar "con" para asignar regiones de la página a modelos individuales - data-bind = "with: VMA"
lexicalscope
3
@flamingpenguin: Sí, pero withno es barato, ver: enlace
mhu
7

He logrado vincular un modelo personalizado a un elemento en tiempo de ejecución. El código está aquí: http://jsfiddle.net/ZiglioNZ/tzD4T/457/

Lo interesante es que aplico el atributo de enlace de datos a un elemento que no definí:

    var handle = slider.slider().find(".ui-slider-handle").first();
    $(handle).attr("data-bind", "tooltip: viewModel.value");
    ko.applyBindings(viewModel.value, $(handle)[0]);
ZiglioUK
fuente
teniendo problemas con ko 2.3, el código anterior está en un controlador de cliente al que se llama cuando aplico el global ko.applyBindings (). Así que ahora aparece el error "No puede aplicar enlaces varias veces al mismo elemento". Todavía estoy tratando de averiguar por qué recibo el error. ¿No podemos aplicar un enlace a la misma variable varias veces, cada una a elementos diferentes?
ZiglioUK
Aquí está la versión con ko 2.3 que no funciona: jsfiddle.net/ZiglioNZ/tzD4T/458
ZiglioUK
Agregar una llamada a ko.cleanNode () antes de llamar a applyBinding a la vista parcial no parece ayudar: jsfiddle.net/ZiglioNZ/tzD4T/459
ZiglioUK
Resuelto: ¡Ni siquiera necesitaba llamar a applyBindings!
ZiglioUK
he editado el código fuente de knockoutjs y ha comentado la parte en la que la función interrumpe "No puedes aplicar enlaces varias veces al mismo elemento", ahora todo funciona bien ... Sé que esta es una solución sucia, pero soy nuevo en la biblioteca, así que No sé cómo no aplicarlo varias veces para mi problema.
Geomorillo