handlebars.js “each” loop inside another “each” - handlebars.js

I have two objects. 1 object is 10 questions, 2 object is 10 answers, I need to output them in nested loops, but that doesn't work.
{{#each questions}}
{{#each answers}}
<p class = "mt-2"> {{this.text}} </p>
<p> {{this.value}} </p>
{{/ each}}
{{/ each}}
I also tried this option:
{{#each questions}}
{{#each ../answers}}
<p class = "mt-2"> {{../ this.text}} </p>
<p> {{this.value}} </p>
{{/ each}}
{{/ each}}
but in this case, each question-answer is displayed 10 times. I tried different options so many times

Looks like the issue is that you've nested two loops. This means that for each question, it will output all the answers every time.
If I'm reading your question right, you're trying to output question1, answer1, question2, answer2, etc., so you'll have to instead look up the corresponding answer inside the loop using an #index.
This can be done using {{#with (lookup ../answers #index)}} to change the context like so:
{{#each questions}}
<p class = "mt-2"> {{this.text}} </p>
<p> {{this.value}} </p>
{{#with (lookup ../answers #index)}}
<p class = "mt-2"> {{text}} </p>
<p> {{value}} </p>
{{/with}}
{{/ each}}

Related

Handlebars Array Cycle

I have this array:
{{#each weather.today }}
<p class="VNAelement timeStamp">BlaBla</p>
<p class="VNAelement">{{ rr }}mm</p>
{{/each}}
Now there will be three loops and on each loop the text BlaBla should be replaced. What is the best way to do this? The data comes from a json API but that string is set manuall.
The best solution is to write a custom helper to check the array index during traversal.
But here, as you are sure of the number of loops (which is 3 array items), you can rely on the #first and #last data-variables.
{{#each weather.today}}
<p class="VNAelement timeStamp">
{{#if #first}}
BlaBla-1 <!-- First item -->
{{else}}
{{#if #last}}
BlaBla-3 <!-- Third item -->
{{else}}
BlaBla-2 <!-- Second item -->
{{/if}}
{{/if}}
</p>
<p class="VNAelement">{{ rr }}mm</p>
{{/each}}

get the `top 4 products from each toptier category sorted by date-added (to bigcommerce)`

BigCommerce Stencil
I totally winged the below snippet. But i need a hint on doing that the correct way. I basically need to get the top 4 products from each toptier category sorted by date-added (to bigcommerce)
{{#each categories}}
{{#each products sort:date-added limit:4}}
{{name}}
{{/each}}
{{/each}}
To add, the syntax I would use is the following. However, I don't have any evidence that such a way exists yet.
home.html
{{> components/product/all-products grid=products.all default_image=theme_settings.default_image}}'
all-products.html being a custom file.
all-products.html
{{#if grid}}
<section class="products-new {{theme_settings.background-for-new-products}}">
<div class="layout-container">
<h1 class="section-title">{{lang 'product.product_blocks.new_products.heading'}}</h1>
<div class="product-grid">
{{#each grid}}
{{> components/product/product-item this show_quickshop=true show_rating=true default_image=../default_image}}
{{/each}}
</div>
</div>
</section>
{{/if}}

How can i can display fields from an item from Collection B referenced by an id from an item from Collection A?

i have two collections
CategoryCollection = new Mongo.Collection("CategoryCollection");
usersWordpressCollection = new Mongo.Collection("usersWordpressCollection");
CategoryCollection hold posts within a category, within the posts objects there is the Author, which comes as an id. take a look at the image below, draw your attention to posts.author
usersWordpressCollection holds the authors whose id (see image below) is referenced in categoryCollection under posts.author
when i display a post, its coming from categoryCollection so i can get the post, the link etc. i can also get the author id however when it comes to this, i want to return, not the id, but the referenced Author information found in the usersWordpressCollection
latest html
<template name="latest">
<ul>
{{#each articles}}
<li class=" home-latest ">
<span class="label"> <a class="" href="/catsingle/CategorySingle/{{_id}}">{{name}}</a></span>
{{#each posts}}
<div class="card">
<div class="category-img">{{{image}}}</div>
<div class="card-divider">
{{title}}
</div>
<div class="card-section">
<p>
{{> authors}}
</p>
</div>
</div>
</li>
{{/each}}
</ul>
</template>
latest js
Template.latest.helpers({
articles: function () {
var id = FlowRouter.getParam('_id');
return CategoryCollection.find({}, {sort: {date_created: -1}, limit:1}).fetch();
}
});
authors html
<template name="authors">
{{#each authors}}
<p>
{{name}}
</p>
{{/each}}
</template>
authors js
Template.authors.helpers({
authors: function () {
var id = this.author;
console.log(id);
var alias = usersWordpressCollection.findOne(id, {fields: {name: 1} });
return alias.name;
console.log(alias.name);
});
As you can see, this.author is the author id found in categoryCollection posts.author. Im trying to find that id in the usersWordpressCollection matching the author, then i want to display the name field of the Author whose id was matched. but i can't seen to get it working, how can i achieve this.
Since there is only one author per post you don't need to iterate over a cursor of authors, you only need one. So where you have:
{{#each authors}}
<p>
{{name}}
</p>
{{/each}}
Instead use:
{{#with author}}
<p>
{{name}}
</p>
{{/with}}
Now, the data context coming into the authors template will be a post object (since you are within an {{#each posts}}. You can therefore construct your author helper as follows:
Template.authors.helpers({
author(){
return usersWordpressCollection.findOne({ id: parseInt(this.author) });
}
});
Since you've indicated that this.author is a string but the id of your user collection is an integer then you need to convert the type - you can do this directly in your query.

Creating UI comment component with blaze

I'm trying to create a comments component with Blaze but i don't know how to handle the replies.
This is the schema for the 'comment' element:
_id, authorId, message, replies (those are comment ids), isReply (boolean).
Then I created a template with html
{{#each message}}
<div class="message">
<h2>{{author}}</h2>
<p>{{message</p>
<a class="button">Reply</a>
</div>
{{#each replies}}
<div class="message">
<h2>{{author}}</h2>
<p>{{message</p>
<a class="button">Reply</a>
</div>
{{/each}}
{{/each}}
Well, how do I handle the replies of the replies? Any Idea?
You need to use the templates recursively! An example
In your case, something like the following:
{{#each message}}
<div class="message">
<h2>{{author}}</h2>
<p>{{message</p>
<a class="button">Reply</a>
</div>
{{#each replies}}
{{> reply}}
{{/each}}
{{/each}}
<template name="reply">
<div class="message">
<h2>{{author}}</h2>
<p>{{message</p>
<a class="button">Reply</a>
{{#each replies}}
{{> reply}}
{{/each}}
</div>
</template>
You'll need a replies helper for the reply template that gets the replies to that reply.

How to filter the data from a collection loop?

Im trying to build a related info widget, based on the data from the YAML front-matter.
Each page on my collection has some tags associated, and the idea would be to only show those pages who have tags in common with the currently viewed page.
I've managed to get the complete tags outputting the existent pages with the following code:
<section class="see-also">
{{#each tags}}
<p>In <span class="tag">{{tag}}</span>:</p>
{{#each pages}}
<li>{{data.title}}</li>
{{/each}}
{{/each}}
</section>
Can I apply some sort of filter on {{#each tags}} ?
Thanks.
There's an inArray helper that you can use to test if the current tag is in the tags collection on the page being currently rendered:
<section class="see-also">
{{#each tags}}
{{#inArray ../page.tags tag }}
<p>In <span class="tag">{{tag}}</span>:</p>
{{#each pages}}
<li>{{data.title}}</li>
{{/each}}
{{/inArray}}
{{/each}}
</section>
You might have to modify the parent path syntax to account for the additional block helper:
<section class="see-also">
{{#each tags}}
{{#inArray ../page.tags tag }}
<p>In <span class="tag">{{tag}}</span>:</p>
{{#each ../pages}}
<li>{{../data.title}}</li>
{{/each}}
{{/inArray}}
{{/each}}
</section>

Resources