This question already has answers here:
How can I get the index of an array in a Meteor template each loop?
(6 answers)
Closed 7 years ago.
I am using meteor Shark branch.
Is there a way to access array index inside each block helper in spacebars?
I am looking for something like this.
{{#each humans}}
{{this.arrayIndex}}
{{/each}}
meteor >= 1.2
Spacebars gained a lot of functionality in 1.2, including a native #index. Helpers are no longer needed to solve this problem - you can simply do this:
<template name="showHumans">
<ul>
{{#each humans}}
<li>{{#index}}: {{name}}</li>
{{/each}}
</ul>
</template>
meteor < 1.2
I saw a similar example using template helpers in the meteor book in the "animations" chapter. You can apply a map to the humans cursor in order to add an index like so:
Template.showHumans.helpers({
humans: function() {
return Humans.find({}, {sort: {hotness: -1}}).map(function(human, index) {
human.rank = index;
return human;
});
}
});
<template name="showHumans">
<ul>
{{#each humans}}
<li>{{rank}}: {{name}}</li>
{{/each}}
</ul>
</template>
As taken from the spacebars documentation:
You can use a special variable #index in the body of #each to get the
0-based index of the currently rendered value in the sequence.
In Meteor 1.0.2.1, you can do the following:
{{#each humans}}
{{this}}
{{/each}}
This is because #each iterates through the array, making the this in each loop simply equal to the current value.
Related
each running after onRendered and Tracker.autorun(if foo is binding subscription data context).
so i cant catch thateach` work is when done.
how to know each is work done, or rework and done?
is it unknown?
Below is an example.
<template name="something">
{{#each foo}}
<bar>bar</bar>
{{/each}}
</template>
I don't see a real use case for this but you can use a helper here that does not add anything to the render output:
<template name="something">
{{#each foo}}
<bar>bar</bar>
{{isDone #index foo}}
{{/each}}
</template>
Template.something.helpers({
isDone(index, arr) {
if (index === arr.length - 1) {
// this was the last element
// to be rendered. do whatever
// you want here
}
}
})
Not that this is not really a best practice and you should think about why you need to know this? If you have performance issues with your rendering you want review your whole template code design and refactor where necessary.
What I want is to get the current array listing from an "#each" command, so for the first one it returns 0, the following 1, and so on.
I can get the current values within it such as {{this.valueName}}, but how do I get the numerical place in the array?
Edit - Code for context:
{{#each entry}}
{{> childtemplate}}
{{/each}}
<template name="childtemplate">
<p class="list-group-item-heading">
{{#index}}<br>
Name: {{this.name}}
</p>
</template>
Using #index gives me this:
Error: Unsupported directive: #index meteor
Just use {{#index}}. You also don't need this, {{valueName}} is sufficient.
I'm trying to pass down the index of an item from an {{#each}} loop into a dynamic template, but am lost on how to get it there (in a clean way).
Current code:
{{#each item}}
{{Template.dynamic template=type data=this}}
{{/each}}
With this, {{#index}} is not accessible in the dynamically loaded template.
I also tried using a template helper, but it doesn't appear the index is tracked in the context.
{{#each item}}
{{Template.dynamic template=type data=itemData}}
{{/each}}
Template.items.helpers({
itemData() {
// can't access index in here
return this;
}
});
Can anyone advise on how I can achieve this?
Thanks!
Solved this using the following pattern:
... Template.Items
{{#each items}}
{{>Template.dynamic itemConfig #index}}
{{/each}}
Template.items.helpers({
itemConfig(index) {
const data = this;
data.index = index;
return {
data,
template: this.type //this.type is where im storing my template name
};
},
});
Using the #index as a helper param, and then Blaze uses the object as a config for the dynamic template!
:)
EDIT: I found another solution. Does the same job, and I prefer how it looks.
{{>Template.dynamic template=type data=(templateData #index)}}
Where templateData is essentially the same helper from before but just returns data with an index prop.
{{#each item}}
{{Template.dynamic template=type index=#index}}
{{/each}}
You can use 'index' in dynamic template to access index
What is the standard way to access outer #each collection values in the loop?
for example:
<template name="example">
{{#each outerCollection}}
<tr>
{{#each innerCollection}}
<td>{{aaa}}</td>
{{/each}}
</tr>
{{/each}}
</template>
Template.example.aaa = function(){
// cannot access outerCollection values
}
in above Template.example.aaa, this points to the inner collection.
I cannot find way to access outerCollection items.
My solution is like below, I am defining my own helper function.
Is it a standard Meteor way to achieve this purpose?
<template name="example">
{{#each outerCollection}}
<tr>
{{#each innerCollection}}
<td>{{myHelper ../outerItem innerItem}}</td>
{{/each}}
</tr>
{{/each}}
</template>
Handlebars.registerHelper('myHelper', function (outItem, inItem) {
// can access outerCollection via outerItem
});
I found a similar question for the case of inner event handler access.
I think you've answered this yourself! Using ../ is documented in https://github.com/meteor/meteor/wiki/Handlebars.
You can use below code to fetch outer collections.
suppose you have collection called as Collection.Customer and Collection.RechargePlan and you are using both in a template for updating Customer.
Customer = {"name":"James", "rechargeplan":"monthly"};
RechargePlan = [{"rechargeplan": "monthly"},{"rechargeplan": "yearly"}];
//Inside template, Bydefault Customer is available.
{{#each RechargePlan}}
{{#if equals ../rechargeplan rechargeplan}}
//Hurray Plan matches
{{/if}}
{{/each}}
In above code, ../rechargeplan is actually Customer.rechargeplan, ../ actually went one step above heirarchy and then accessed the field if available, since Customer is already available to template, it's field is picked up.
Is it possibly to use global variables in Handlebars conditionals? I'm writing an app that lists a lot of objects, and I want users to be able to control which details are listed. For example, displaying only first names in a list of people, like so:
<ul>
{{#each people}}
<li>
<p>{{firstName}}</p>
{{#if displayLastnames}}
<p>{{lastName}}</p>
{{/if}}
</li>
{{/each}}
</ul>
I don't want to actually modify the data (for example, by removing the lastName attribute and doing {{#if lastName}}).
You can also register a global helper named 'displayLastnames' and use it in a if :
Handlebars.registerHelper('displayLastnames', function(block) {
return displayLastnames; //just return global variable value
});
and just use it as in your sample :
{{#if displayLastnames}}
<p>{{lastName}}</p>
{{/if}}
Handlebars namespaces the variables so you can't directly access global variables. Probably the easiest thing to do is to add your own helper, something simple like this:
Handlebars.registerHelper('if_displayLastnames', function(block) {
if(displayLastnames)
return block.fn(this);
else
return block.inverse(this);
});
and then in your template:
{{#if_displayLastnames}}
<p>{{lastName}}</p>
{{/if_displayLastnames}}
You'd probably want to put your "global" variables in their own namespace of course.
Demo: http://jsfiddle.net/ambiguous/Y34b4/