Accès au contexte parent dans les modèles Meteor et les aides de modèle

Je suis dans une situation de contexte de modèle que j’ai du mal à trouver un moyen de contourner.

Voici le modèle en question:

{{#each votes}} 

{{question}}

    {{#each participants}}
  • {{email}}

    {{#each ../options}} {{option}} {{/each}}
  • {{/each}}
{{/each}}

Et voici un exemple de document de vote:

 { _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 } ] } 

Et voici le problème …

Lorsque le modèle entre dans le #each pour les participants, il n’a plus access au contexte de vote et n’a donc pas access aux options disponibles pour chaque vote.

Je peux quelque peu contourner ce ../options en utilisant le chemin d’access du guidon ../options pour revenir dans le contexte parent, mais cela n’affecte pas le contexte de l’assistant de template. this dans Template.vote.is_selected_option fait référence au participant actuel, pas au vote ou à l’ option , et n’a aucun moyen de savoir quelle option nous sums en train de parcourir.

Des suggestions sur la façon de contourner ce problème, sans avoir recours à la manipulation du DOM et aux manigances jQuery?

C’est un problème de modèle qui a été soulevé à plusieurs resockets pour moi. Nous avons besoin d’une méthode formelle pour atteindre la hiérarchie du contexte du modèle, dans les modèles, les aides de modèle et les événements de modèle.

Ce n’est pas particulièrement joli, mais j’ai fait quelque chose comme ça:

   // and in the js: Template.forLoop.helpers({ augmentedParticipants: function() { var self = this; return _.map(self.participants,function(p) { p.parent = self; return p; }); } }); 

Il est similaire à l’approche suggérée par AVGP, mais augmente les données au niveau de l’aide plutôt que du niveau de la firebase database, ce qui, selon moi, est un peu plus léger.

Si vous avez envie, vous pouvez essayer d’écrire une aide de bloc Handlebars eachWithParent qui abstraire cette fonctionnalité. Les extensions de Meteor aux guidons sont documentées ici: https://github.com/meteor/meteor/wiki/Handlebars

Il semble que depuis Spacebars (le nouveau moteur de template de Meteor) , vous avez access au contexte parent dans les blocs {{#each}} utilisant ../ .

Dans Meteor 0.9.1, vous pouvez également écrire une aide et utiliser Template.parentData() dans son implémentation.

Je ne connais pas la manière formelle (s’il y en a une), mais pour résoudre votre problème, je lierais les participants avec l’ID parent comme ceci:

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

et utilisez ce parent_id dans les helpers, les événements, etc. pour revenir au parent en utilisant findOne. C’est évidemment une chose sous-optimale à faire, mais c’est la manière la plus simple qui me vienne à l’esprit tant qu’il n’y a aucun moyen de référencer le contexte parent. Peut-être y a-t-il un moyen mais il est très bien caché dans le fonctionnement interne de Meteor sans mention dans les documents, si oui: Veuillez mettre à jour cette question si vous en trouvez une.

C’est un long coup, mais peut-être que cela pourrait fonctionner:

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

Cela devrait rendre la vie plus facile.

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

Allez-y et changez

 p.parent = self._id; 

à tout ce que vous voulez accéder dans le contexte parent.

Corrigé:

 // 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); }); 

Cela fonctionne 🙂 sans erreur

Enregistrez simplement un assistant de modèle global:

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

et l’utiliser dans vos modèles HTML en tant que:

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

======= EDIT

Pour Meteor 1.2+, vous utilisez:

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

J’ai été bloqué de la même manière et j’ai constaté que l’approche Template.parentData () suggérée dans d’autres réponses ne fonctionnait pas dans les gestionnaires d’événements (voir https://github.com/meteor/meteor/issues/5491 ). L’utilisateur Lirbank a publié cette solution simple:

Transmettez les données du contexte externe à un élément HTML dans le contexte interne, dans le même modèle:

 {{#each companies}} {{#each employees}} Do something {{/each}} {{/each}} 

Maintenant, l’ID de l’entreprise est accessible depuis le gestionnaire d’événements avec quelque chose comme:

 $(event.currentTarget).attr('companyId') 
 "click .selected":function(e){ var parent_id = $(e.currentTarget).parent().attr("uid"); return parent_id }, 
  {{#each all_req_doc}} 
{{/each}}

{{#each parent}}

{{#each child}}

{{/each}}

{{/each}}

Le _id n’est pas le _did de la chose, c’est l’id du parent!