tutorial react examples apps meteor

react - meteor tutorial



Acceder al contexto principal en plantillas de Meteor y ayudantes de plantilla (9)

Es una posibilidad remota, pero tal vez esto podría funcionar:

{{#with ../}} {{#each options}} {{this}} {{/each}} {{/with}}

Me encuentro con una situación de contexto de plantilla que me cuesta mucho encontrar un camino.


Aquí está la plantilla en cuestión:

{{#each votes}} <h3>{{question}}</h3> <ul> {{#each participants}} <li> <p>{{email}}</p> <select name="option-select"> {{#each ../options}} <option value="{{option}}" class="{{is_selected_option}}">{{option}}</option> {{/each}} </select> </li> {{/each}} </ul> </div> {{/each}}


Y aquí hay un ejemplo de un documento de votación:

{ _id: ''32093ufsdj90j234'', question: ''What is the best food of all time?'' options: [ ''Pizza'', ''Tacos'', ''Salad'', ''Thai'' ], participants: [ { id: ''2f537a74-3ce0-47b3-80fc-97a4189b2c15'' vote: 0 }, { id: ''8bffafa7-8736-4c4b-968e-82900b82c266'' vote: 1 } ] }


Y aquí está el problema ...

Cuando la plantilla cae en el #each para los participantes, ya no tiene acceso al contexto del vote y, por lo tanto, no tiene acceso a las opciones disponibles para cada voto.

De alguna manera, puedo evitar esto utilizando la ruta de acceso de ../options para volver al contexto principal, pero esto no afecta el contexto del helper de plantilla, por lo que this en Template.vote.is_selected_option refiere al participant actual, no a la vote u option actual, y no tiene forma de saber a qué option nos referimos actualmente.

¿Alguna sugerencia sobre cómo solucionar esto, sin recurrir a la manipulación DOM y las travesuras jQuery?

Este es un problema de creación de plantillas que me ha surgido muchas veces. Necesitamos una forma formal de alcanzar la jerarquía de contexto de la plantilla, en plantillas, asistentes de plantilla y eventos de plantilla.


Esto debería hacer la vida más fácil.

// use #eachWithParent instead of #each and the parent._id will be passed into the context as parent. Handlebars.registerHelper(''eachWithParent'', function(context, options) { var self = this; var contextWithParent = _.map(context,function(p) { p.parent = self._id; return p; }); var ret = ""; for(var i=0, j=contextWithParent.length; i<j; i++) { ret = ret + options.fn( contextWithParent[i] ); } return ret; });

Adelante y cambia

p.parent = self._id;

a lo que quieras acceder en el contexto principal.

Arreglado:

// https://github.com/meteor/handlebars.js/blob/master/lib/handlebars/base.js // use #eachWithParent instead of #each and the parent._id will be passed into the context as parent. Handlebars.registerHelper(''eachWithParent'', function(context, options) { var self = this; var contextWithParent = _.map(context,function(p) { p.parent = self._id; return p; }); return Handlebars._default_helpers.each(contextWithParent, options); });

Esto funciona :) sin error


Me quedé atrapado de una manera similar y descubrí que el enfoque de Template.parentData () sugerido en otras respuestas actualmente no funciona dentro de los manejadores de eventos (ver https://github.com/meteor/meteor/issues/5491 ). El usuario Lirbank publicó esta solución simple:

Pase los datos del contexto externo a un elemento html en el contexto interno, en la misma plantilla:

{{#each companies}} {{#each employees}} <a href="" companyId="{{../id}}">Do something</a> {{/each}} {{/each}}

Ahora se puede acceder a la identificación de la compañía desde el controlador de eventos con algo como

$(event.currentTarget).attr(''companyId'')


No conozco la forma formal (si es que hay una), pero para resolver su problema, vincularía a los participantes con la ID de los padres de la siguiente manera:

{ _id: "1234", question: "Whats up?", ... participants: [ { _id: "abcd", parent_id: "1234", vote: 0 } ] }

y use este parent_id en helpers, events, etc. para saltar al padre usando findOne. Obviamente, esta es una tarea subóptima, pero es la forma más fácil que se me ocurre siempre que no haya forma de hacer referencia al contexto principal. Tal vez hay una manera, pero está muy bien escondida en el funcionamiento interno de Meteor sin mencionar en los documentos, de ser así: actualice esta pregunta si encuentra una.


No es particularmente bonito, pero he hecho algo como esto:

<template name=''forLoop''> {{#each augmentedParticipants}} {{> participant }} {{/each}} </template> <template name=''participant''> ... Question: {{this.parent.question}} ... </template> // and in the js: Template.forLoop.helpers({ augmentedParticipants: function() { var self = this; return _.map(self.participants,function(p) { p.parent = self; return p; }); } });

Es similar al enfoque sugerido por AVGP, pero aumenta los datos en el nivel de ayuda en lugar del nivel de base de datos, que creo que es un poco más ligero.

Si te apetece, podrías intentar escribir un ayudante de bloque de Handlebars eachWithParent que eachWithParent esta funcionalidad. Las extensiones de Meteor para los manubrios están documentadas aquí: https://github.com/meteor/meteor/wiki/Handlebars



Simplemente registre un asistente de plantilla global:

Template.registerHelper(''parentData'', function () { return Template.parentData(1); } );

y utilízalo en tus plantillas HTML como:

{{#each someRecords}} {{parentData.someValue}} {{/each}}

======= EDITAR

Para Meteor 1.2+, debes usar:

UI.registerHelper(''parentData'', function() { return Template.parentData(1); });


{{#each parent}}

{{#each child}}

<input type="hidden" name="child_id" value="{{_id}}" />

<input type="hidden" name="parent_id" value="{{../_id}}" />

{{/each}}

{{/each}}

¡El _id NO es el _did de la cosa, es la identificación del padre!


"click .selected":function(e){ var parent_id = $(e.currentTarget).parent().attr("uid"); return parent_id },

<td id="" class="staff_docs" uid="{{_id}}"> {{#each all_req_doc}} <div class="icheckbox selected "></div> {{/each}} </td>