2011-09-05 8 views
9

Estoy trabajando en una página que está siendo servidor desde una aplicación ASP.NET MVC3 que quiero usar en KnockoutJS.Conexión knockoutjs a un elemento DOM ya poblada

En la vista me estoy aprobó una Modelo poblado (que estoy convirtiendo a KnockoutJS viewModel) y quiero construir algo del lado del servidor DOM. Esto parece lógico ya que ya tengo los objetos para generar el HTML inicial y proporcionará una mejor experiencia a los usuarios, ya que no habrá un retraso entre la carga de la página y la población DOM (también significa que tengo una funcionalidad básica para no -JavaScript clientes).

Después de investigar Asumo que necesito para crear una costumbre bindingHandler así que creé esto:

ko.bindingHandlers.serverForEach = { 
    init: function() { /* no-op */ }, 
    update: function() { 
     //call off to the built in loop handler 
    } 
}; 

Así que mi pensamiento era que crear un controlador que no hace nada en la fase init (como el DOM ya está lleno) y en la fase update, solo insertaré el nuevo valor. Me gustaría aprovechar las plantillas incorporadas, así que esta también puede ser una solución genérica.

El problema es que todo se derrumba en este escenario. Si el init no hace nada, el update falla ya que el bindingContext que aparece como el último argumento parece incorrecto, y si incluyo el init, destruirá el HTML existente.

¿Alguien ha intentado esto/sabe lo que debería hacer para apoyar este escenario o está demasiado lejos de lo que puede/debería hacer?

Además, no quiero tener un elemento DOM por separado para el HTML generado por el servidor que el HTML Knockout.

Respuesta

8

Creo que entiendo cuál es tu problema. Desea completar el marcado inicialmente para usuarios que no sean js y simplemente sobrescribirlo cuando se enlace a KO.

Para enlaces simples como texto esto no es un problema, simplemente incluya el atributo de enlace de datos en el marcado desde el servidor o incluya en tiempo de ejecución y listo. Para la plantilla de foreach, las cosas vinculadas son un poco más difíciles ya que agregarán valores cuando estén vinculados.

Here is a jsfiddle que describe el escenario anterior y muestra la solución a continuación. Es un poco básico, pero debería ayudarte a empezar.

La idea básica es borrar el elemento en init y luego delegar el resto en el enlace de plantilla existente.

ko.bindingHandlers.serverForEach = { 
    init: function(element, valueAccessor, allBindingsAccessor, viewModel) { 
     // clear the list first 
     $(element).children().remove(); 
    }, 
    update: function(element, valueAccessor, allBindingsAccessor, viewModel) { 
     ko.bindingHandlers['template'].update(element, valueAccessor, allBindingsAccessor, viewModel); 
    } 
}; 

Espero que esto ayude.

2

En caso de que alguien necesita que esto funcione para knockout.js 2.0+ (nótese el bindingContext de actualización)

ko.bindingHandlers.serverForEach = { 
init: function(element, valueAccessor) { 
     $(element).children().remove(); 
     return ko.bindingHandlers.template.init(element, valueAccessor); 
    }, 
    update: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) { 
     return ko.bindingHandlers.template.update(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext); 
    } 
}; 
Cuestiones relacionadas