2012-01-09 13 views
7

me he encontrado con varias situaciones en las que tengo que codificar mi llamada plantilla de la siguiente manera:sintaxis extendida para pasar parámetros a las plantillas KnockoutJS

<!-- ko template: {name: 'paginatedList', 
        data: {listContainer: paginatedResults, itemTemplate: $parent.template}} --> 
<!-- /ko --> 

porque además de mi objeto de datos (por ejemplo, paginatedResults), I necesita pasar información suplementaria, como el nombre de la plantilla para usar en la representación de elementos. Como otro ejemplo, al representar un elemento en una lista, es posible que necesite conocer la configuración actual de un filtro que está almacenado en algún contexto lógicamente muy alejado del elemento en una lista.

En lugar de tener que retorcer mi modelo de datos (en el ejemplo anterior, en sustitución de paginatedResults con {listContainer: paginatedResults, itemTemplate: $parent.template}}, sería bueno tener un poco de sintaxis en plantillas que me permite pasar alrededor (y acccrue como plantillas son evaluados de forma jerárquica) un poco de contexto adicional que puede ser que necesite una plantilla están anidadas cuando se representa a sí mismo.

creo que lo que se pregunta sobre es la posibilidad de añadir un parámetro adicional (opcional) a las ko.bindingHandlers funciones (init y update) para que se vean como esto:

function (element, 
      valueAccessor, 
      allBindingsAccessor, 
      viewModel, 
      bindingContext, 
      context) 

Al codificar el ejemplo anterior, debería ser capaz de decir algo como

<!-- ko template: {name: 'paginatedList', 
        data: paginatedResults, 
        context: {itemTemplate: $parent.template}} --> 
<!-- /ko --> 

o mejor aún,

<!-- ko template: {name: 'paginatedList', 
        data: paginatedResults, 
        itemTemplate: $parent.template} --> 
<!-- /ko --> 

y tienen itemTemplate convertido en una variable que pueda hacer referencia a las plantillas anidadas y data-bind atributos.

¿Tiene esto sentido? No entiendo muy bien lo difícil que sería implementarlo. Supongo que una cosa de la que preocuparse son las colisiones de nombres, pero algunas convenciones de nombres podrían eludir eso.

génica

Respuesta

9

Sin cambios a Knockout núcleo, creo que lo mejor que se podría hacer es una unión que se crea una estructura similar a lo que actualmente está pasando envoltura.

Encuadernación podría parecerse a:

ko.bindingHandlers.templateWithContext = { 
    init: ko.bindingHandlers.template.init, 
    update: function(element, valueAccessor, allBindings, data, context) { 
     var options = ko.utils.unwrapObservable(valueAccessor()); 

     ko.utils.extend(context, options.context); 

     return ko.bindingHandlers.template.update.apply(this, arguments); 
    } 
}; 

Se podría llamar así:

<div data-bind="templateWithContext: { name: 'itemsTmpl', data: items, context: { title: 'First' } }"></div> 

Este es un ejemplo: http://jsfiddle.net/rniemeyer/QNvFn/

Parece que está utilizando plantillas nativas, pero si está usando todavía plantillas de jQuery, entonces incluyó un templateOptionsfeature que usó la característica options de las plantillas de jQuery para pasar datos de contexto. Esto no está disponible en las plantillas nativas. La recomendación general ahora es usar $root, $parent y $parentsvariables para acceder a la información o pasar un objeto como data en la forma que describió en su publicación.

+0

Gracias! Estoy de acuerdo en que hace lo correcto, pero no es suficiente para garantizar un controlador vinculante adicional. Sería interesante ver con qué frecuencia aparece este patrón en aplicaciones complejas. –

+0

Gracias me ayuda mucho.Si escribo un envoltorio de plantilla, ¿puedo establecer el nombre de la plantilla dentro del 'init'? – tbruyelle

+0

@tbruyelle - definitivamente puede establecer el nombre. La idea sería que dentro de su encuadernación empaqueta las opciones que desea pasar al encuadernado de plantilla real. Aquí hay una muestra que es tal vez un poco más genérica de lo que necesita (simplemente podría establecer el nombre en el objeto valueAccessor()): http://jsfiddle.net/rniemeyer/7rcFD/ –

Cuestiones relacionadas