Anton Scotte
Anton Scotte

Reputation: 439

Passing variable from parent template to child template in meteor

I have a parent template with several nested child templates inside it. And inside each nested template I have a string generated from an array. A simplified model of my html:

<template name="parent">
   <a class="logId">Console log parent Id</a>
   {{> firstChild}}
   {{> secondChild}}
</template>

In addition my child templates have an each loop like this:

<template name="firstChild">
   {{#each users}}
      {{this}}
      {{> adminSelectUser}}
   {{/each}}
</template>

<template name="adminSelectUser">
   <a class="selectUser">SelectUser</a>
</template>

In my js code:

Template.parent.events({
    'click .logId': function () {
       var eventId = this._id._str;
       console.log(eventId);
});

Template.adminSelectUser.events({
   'click .selectUser': function(template){
      var userString = this.valueOf();
      console.log(userString);
    }
 });

To this point I get it to work and in both of my templates I can find the id of my parent and the string of my user as I want it to do. But then I would also want to use both my variables eventId and userString in the same method call, called from the template adminSelectUser. Is there any way that I can pass the eventId found in the parent template down to the adminSelectUser template so that I can work with both variables with the same method call.

This is what I aim to do with my server methods:

Meteor.methods({
    removeUser: function(){
       Meets.update({_id: eventId}, {$pull : {usersApplied: userString}});
  }
}); 

I want my server method to recognize the eventId and the userString and get them to work together when I call the method later on in the adminSelectUser template.

Hope this is clear enough!

Upvotes: 3

Views: 1854

Answers (1)

numbers1311407
numbers1311407

Reputation: 34072

There are several ways to go about this.

  1. Using Template.parentData

    You can traverse the template hierarchy from within template JS using Template.parentData(n) where n is the number of levels up in the hierarchy you want to go. So specifically for your example:

    Template.adminSelectUser.events({
      'click .selectUser': function(template){
        var user = this;
        var parentId = Template.parentData(2)._id;
    
        myRemoveMethod(parentId, user);
      }
    });
    

    However, this means that the inner template relies on always being rendered within the same hierarchy, which kinda has a bad smell. If the templates are tightly coupled and this is the case (which is likely) then using parentData is probably fine. However, if a template has data dependencies it does make sense to pass the appropriate data explicitly (see #2).

  2. Pass the data into the templates explicitly.

    <template name="firstChild">
      {{#each users}}
        {{this}}
        {{> adminSelectUser user=this parent=..}}
      {{/each}}
    </template>
    

    In your example, when you pass no argument to a template render, the data context is assumed to be this. Here instead we pass a user and a parent into the template (Note the use of .. here to reference this outside of the users loop). Your handler would then look more like:

    Template.adminSelectUser.events({
      'click .selectUser': function() {
        var data = Template.currentData();
        myRemoveMethod(data.parent._id, data.user);
      }
    });
    

Upvotes: 2

Related Questions