How to pass data variable from each to the with in Meteor? - meteor

I am trying to pass git variable to settings which is wrapping with with as shown below
If we can see right now it is setting.gitlab but i want to make it dynamically like setting.git where git is a variable mentioned in each loop .
{{#each git in gitlabFields}}
{{#with settings.gitlab}}
<div data-value={{#index}}>{{git}}</div>
<div>hihi</div>
<div class="rc-user-info__row">
<div class="rc-input">
<label class="rc-input__label">
<div >
<div class="rc-input__title" style="display: inline-block;" >{{_ label}}{{equal default value '*'}}</div>
</div>
<!-- {{#each gitlabFields}} -->
<div id="dynamicFields">
<div class="rc-input__wrapper" >
<input type="text" name="{{git}}" value="{{value}}" class="rc-input__element js-input" disabled="{{./disabled}}"/>
</div>
</div>
<!-- {{/each}} -->
</label>
</div>
</div>
{{/with}}
{{/each}}
git variable is not accessible here settings.git
Its showing undefined .

Assuming settings is an accessible Object, you can write a helper, that resolves the value:
Template.myTemplate.helpers({
getGitSettings (settings, key) {
return settings[key]
}
})
If you want to decouple settings from the template or avoid passing it through the whole display list you can also define it within the Template module as private variable:
const gitSettings = { ... };
Template.myTemplate.helpers({
getGitSettings (settings, key) {
return gitSettings[key]
}
})
If this pattern is used among many Templates you can also define a global helper:
const gitSettings = { ... };
Template.registerHelper('gitSettings', function (key) {
return gitSettings[key]
})
and use it via
{{#each field in gitlabFields}}
{{#with gitSettings field}}...{{/with}}
{{/each}}

Related

Meteor get ID of template parent

I have two Collection : a collection A which include array of B ids.
Template A :
<template name="templateA">
Name : {{name}} - {{_id}}
{{#each allBsOfThisA}}
{{> Bdetail}}
{{/each}}
Add B for this A
</template>
Note : in this templateA, I list all A and their detail informations. At bottom of the A, I putted a link to add a B.
Template of Bsubmit :
<div class="form-group {{errorClass 'nameOfB'}}">
<label class="control-label" for="nameOfB">nameOfB</label>
<div class="controls">
<input name="nameOfB" id="nameOfB" type="text" value="" placeholder="nameOfB" class="form-control"/>
<span class="help-block">{{errorMessage 'nameOfB'}}</span>
</div>
</div>
<input type="submit" value="Submit" class="btn btn-primary"/>
On the Bsubmit script : I want to get the ID of A. I tried with template.data._id but it's not working :
Template.Bsubmit.events({'submit form': function(e, template) {
e.preventDefault();
console.log("template.data._id: " + template.data._id);
var B = {
name: $(e.target).find('[name=name]').val(),
AId : template.data._id
};
}
});
EDIT :
BSubmit's iron-router part :
Router.route('Bsubmit ', {name: 'Bsubmit '});
Neither the template nor the route does know about the A-instance of the other template/route.
So one solution would be to pass the id to the route, which allows you to fetch the instance or use the id directly:
Template:
<template name="templateA">
Name : {{name}} - {{_id}}
{{#each allBsOfThisA}}
{{> Bdetail}}
{{/each}}
Add B for this A
</template>
Route:
More information about passing arguments to a route
Router.route('/Bsubmit/:_id', function () {
var a = A.findOne({_id: this.params._id});
this.render('Bsubmit', {data: a});
});
Then you could use template.data._id in the event.
Another solution would be to embed the form into the other view, so you can access the data of the parent template in there (documentation of parentData).

Template.dynamic is not passing data context

I have a list template (#each) in a package that I plan to use across many different collections. Since the template is in a package they are not easily customizable. So I figured this was a great example to use Template.dynamic. Everything works except passing data.
.. I pull the data into the routed page and manipulate the data to match the dynamic template.
Template.usersIndex.helpers({
items: function() {
var users = Meteor.users.find({}).fetch();
var items = users.filter(function(user) {
return user;
}).map(function(user){
return {
name: user.profile.name,
description: user.emails[0].address,
tidbit: "hello"
};
});
return items
}
});
... the data passes perfectly to the usersIndex template.
<template name="usersIndex">
<div id="gc-users-index-navbar">
<h2>Title</h2>
</div>
<div id="gc-users-index" class="inner-content">
{{> Template.dynamic template="strataIndexItem" data="items" }}
</div>
</template>
... But no dice, the dynamic template is rendered but no data.
<template name="themeIndex">
<div class="list-group">
{{#each items }}
<div class="list-group-item">
<div class="row-content">
<div class="least-content">{{tidbit}}</div>
<h4 class="list-group-item-heading">{{name}}</h4>
<p class="list-group-item-text">{{description}}</p>
</div>
</div>
<div class="list-group-separator"></div>
{{/each}}
</div>
</template>
You pass data as string?
{{> Template.dynamic template="strataIndexItem" data="items" }}
You should pass data as variable, without ""
{{> Template.dynamic template="strataIndexItem" data=items }}
Also check if your strataIndexItem template is named strataIndexItem:
<template name="strataIndexItem">
...
</template>

Getting the outer context of a Meteor Template

I have the following use-case: There are rooms which have beds inside. (Bummer...)
There is a loop of rooms which uses a template "room".
<template name="rooms">
{{#each availableRooms}}
{{> room}}
{{/each}}
</template>
This template gets for each iteration a room. This is accessible by this.
<template name="room">
<div class="room-outer">
<button type="button" class="btn" data-toggle="collapse" data-target="#list-{{_id}}">
{{name}} : {{getBeds this}} beds free.
</button>
<div id="list-{{_id}}" class="collapse in room-inner">
{{#each guests_id}}
<div class="bed">
<div class="blanket">
{{showUser this}}
</div>
</div>
{{/each}}
</div>
</div>
</template>
Now I like to calculate some special value which I do by extending the template. I need now to pass the this variable to the getBeds function. Is it possible to do this by grabing outside the template and get the room into the function?
Template.room.getBeds = function (room) {
if (room.guests_id)
return room.beds - _.size(room.guests_id);
else
return room.beds;
};
Basically I don't want to have to write {{getBeds this}} but only {{getBeds}}
Shouldn't this work?
Template.room.getBeds = function () {
if (this.guests_id)
return this.beds - _.size(this.guests_id);
else
return this.beds;
};
See the docs:
Helpers can take arguments, and they receive the current template data in this:

What is "this" in Meteor's "Template.myTemplate.rendered" callback?

According to the docs.meteor, in the body of the "Template.myTemplate.rendered" callback, "this" is a template instance object.
However, when I insert a "debugger" line in the callback and use the browser dev tools to check, the value of "this" is "window". Am I doing something wrong?
I'm using the Leaderboard example - here's the handlebars template:
<template name="leaderboard">
{{#each players}}
{{> player}}
{{/each}}
{{#if selected_name}}
<div class="details">
<div class="name">{{selected_name}}</div>
<input type="button" class="inc" value="Give 5 points" />
<input type="button" class="fastclick inc" value="Give 5 points - fast" />
</div>
{{/if}}
{{#unless selected_name}}
<div class="none">Click a player to select</div>
{{/unless}}
</template>
<template name="player">
<div class="player {{selected}} fastclick">
<span class="name">{{name}}</span>
<span class="score">{{score}}</span>
</div>
</template>
And the "Template.leaderboard.rendered" callback:
Template.leaderboard.rendered = function (){
Meteor.defer(function() {
debugger;
new FastClick(document.body);
console.log("Template.leaderboard.rendered: " + JSON.stringify(this));
});
}
}
I think your problem is that this is inside the Meteor.defer callback, which means that the context of this has changed. Try caching this in a variable, and then outputting that variable in console.log(). For example:
Template.leaderboard.rendered = function (){
var self = this;
Meteor.defer(function() {
debugger;
new FastClick(document.body);
console.log("Template.leaderboard.rendered: " + self );
});
}
}
In the body of the callback, this is a template instance object that is unique to this occurrence of the template and persists across re-renderings. Use the created and destroyed callbacks to perform initialization or clean-up on the object.
Source: http://docs.meteor.com/#template_rendered
So this references the particular instance of your template that you are rendering.

Adding an user field to a Meteor record?

Right now, my Posts model has a title and a content field:
client/client.js:
Meteor.subscribe('all-posts');
Template.posts.posts = function () {
return Posts.find({});
};
Template.posts.events({
'click input[type="button"]' : function () {
var title = document.getElementById('title');
var content = document.getElementById('content');
if (title.value === '') {
alert("Title can't be blank");
} else if (title.value.length < 5 ) {
alert("Title is too short!");
} else {
Posts.insert({
title: title.value,
content: content.value,
author: userId #this show displays the id of the current user
});
title.value = '';
content.value = '';
}
}
});
app.html:
<!--headder and body-->
<div class="span4">
{{#if currentUser}}
<h1>Posts</h1>
<label for="title">Title</label>
<input id="title" type="text" />
<label for="content">Content</label>
<textarea id="content" name="" rows="10" cols="30"></textarea>
<div class="form-actions">
<input type="button" value="Click" class="btn" />
</div>
{{/if}}
</div>
<div class="span6">
{{#each posts}}
<h3>{{title}}</h3>
<p>{{content}}</p>
<p>{{author}}</p>
{{/each}}
</div>
</div>
</div>
</template>
I tried adding an author field (already did meteor add accounts-password and accounts-login):
author: userId
But it just shows the id of the current user who is logged in.
I would like it to show the email of the author of the post instead.
How to accomplish that?
I think you can get the email with
Meteor.users.findOne(userId).emails[0];
#danielsvane is correct, but since your Post document's author field stores the _id of the author and not the email address, you'll need a template helper in order for the template to know how to get the email address. Try the following:
// html
...
<div class='span6'>
{{#each posts}}
{{> postDetail}}
{{/each}}
</div>
...
<template name="postDetail">
<h3>{{title}}</h3>
<p>{{content}}</p>
<p>{{authorEmail}}</p>
</template>
// javascript
Template.postDetail.helpers({
// assuming the `author` field is the one storing the userId of the author
authorEmail: function() { return Meteor.users.findOne(this.author).emails[0]; }
});
If it's always showing the current user and not the user who is the author of the post, then the problem lies in how you're setting the value of the userId variable in your event handler, which isn't code that you showed in your question.

Resources