tutorial template react guide framework development apps meteor meteor-blaze

meteor - template - Cómo obtener la instancia de la plantilla principal(de la plantilla actual)



meteor template events (5)

¿Hay una forma limpia de obtener la plantilla principal de la plantilla actual? Nada está documentado oficialmente en la API de Meteor. Estoy hablando de Blaze.TemplateInstance , no del contexto (es decir, no de Template.parentData ).


¿Hay una forma limpia de obtener la plantilla principal de la plantilla actual?

Actualmente, ninguno de los cuales conozco, pero se supone que esto sucederá en el futuro como parte de una "mejor API para el diseño de componentes reutilizables" (esto se discute en la hoja de ruta Meteor post 1.0 ).

Por el momento, aquí hay una solución que estoy usando en mis proyectos:

// extend Blaze.View prototype to mimick jQuery''s closest for views _.extend(Blaze.View.prototype,{ closest:function(viewName){ var view=this; while(view){ if(view.name=="Template."+viewName){ return view; } view=view.parentView; } return null; } }); // extend Blaze.TemplateInstance to expose added Blaze.View functionalities _.extend(Blaze.TemplateInstance.prototype,{ closestInstance:function(viewName){ var view=this.view.closest(viewName); return view?view.templateInstance():null; } });

Tenga en cuenta que esto solo es compatible con las plantillas principales con nombre y se supone que funciona de la misma manera que jQuery lo closest para recorrer los nodos de las vistas principales desde un elemento secundario hasta la plantilla superior (cuerpo), buscando la plantilla con el nombre adecuado.

Una vez que estas extensiones de Blaze se hayan registrado en algún lugar de tu código de cliente, puedes hacer cosas como estas:

HTML

<template name="parent"> <div style="background-color:{{backgroundColor}};"> {{> child}} </div> </template> <template name="child"> <button type="button">Click me to change parent color !</button> </template>

JS

Template.parent.created=function(){ this.backgroundColor=new ReactiveVar("green"); }; Template.parent.helpers({ backgroundColor:function(){ return Template.instance().backgroundColor.get(); } }); Template.child.events({ "click button":function(event,template){ var parent=template.closestInstance("parent"); var backgroundColor=parent.backgroundColor.get(); switch(backgroundColor){ case "green": parent.backgroundColor.set("red"); break; case "red": parent.backgroundColor.set("green"); break; } } });


Al final, extendí las instancias de la plantilla de manera similar con los datos principales de Meteor, como este:

/** * Get the parent template instance * @param {Number} [levels] How many levels to go up. Default is 1 * @returns {Blaze.TemplateInstance} */ Blaze.TemplateInstance.prototype.parentTemplate = function (levels) { var view = this.view; if (typeof levels === "undefined") { levels = 1; } while (view) { if (view.name.substring(0, 9) === "Template." && !(levels--)) { return view.templateInstance(); } view = view.parentView; } };

Ejemplo de uso: someTemplate.parentTemplate() para obtener el padre inmediato


Lo que he estado haciendo hasta ahora es que si necesito acceder a la instancia principal en la función de una plantilla secundaria, trato de refactorizar esta función para declararla en la plantilla principal y luego pasarla como argumento al niño, quien entonces puede ejecutarlo.

Como ejemplo, digamos que quiero incrementar una variable de plantilla en la plantilla principal desde dentro de la plantilla secundaria. Podría escribir algo como esto:

Template.parentTemplate.onCreated(function () { var parentInstance = this; parentInstance.count = new ReactiveVar(1); }); Template.parentTemplate.helpers({ incrementHandler: function () { var parentInstance = Template.instance(); var count = parentInstance.count.get(); return function () { var newCount = count + 1; parentInstance.count.set(newCount); }; } });

Luego incluye la plantilla de mi hijo:

{{> childTemplate handler=loadMoreHandler}}

Y configurar mi evento:

Template.childTemplate.events({ ''click .increment-button'': function (event, childInstance) { event.preventDefault(); childInstance.data.handler(); } });


Puedes usar un paquete como la extensión de plantilla de Aldeed

El siguiente método está disponible allí:

templateInstance.parent(numLevels, includeBlockHelpers)


Si no desea extender Blaze.TemplateInstance , puede acceder a la instancia principal de esta forma:

Template.exampleTemplate.onRendered(function () { const instance = this; const parentInstance = instance.view.parentView.templateInstance(); });

Solo probado en Meteor 1.4.x