Meteor with Blaze: My helper is not working with {{ #each }} loop - meteor

I am using Blaze with Meteor.
I have announcements_list.html
<template name="AnnouncementsList">
<div class="announcements">
<ul class="collection">
{{ #each announcements }}
{{ >announcementItem }}
{{ /each }}
</ul>
</div>
</template>
And announcements_list.js
Template.AnnouncementsList.helpers({
announcements: function() {
return Announcements.find({}, {sort: {createdAt: -1}});
}
});
If I remove the {{ each }} loop, i can read {{ >announcementItem }}. So I think the problem is the function in the helper. Help me please =.= ...

Is there an announcementItem in your Announcements db or are you trying to access data from a template? If the former, your blaze call should be {{announcementItem}}. In an #each, #unless or #with there is no arrow needed.

You are rendering the same template for every item in announcements. Where this template get data from? I would make something like this:
<template name="AnnouncementsList">
<div class="announcements">
<ul class="collection">
{{#each item in announcements}}
{{> announcementItem item}}
{{/each }}
</ul>
</div>
</template>
Then full item object will be accessible in your announcementItem through
Template.instance().data in helpers and events
this.data in onCreated and onRendered.

Related

Pulling data from collection using Iron router

I have a small issue. The below code snippet works well if i directly dump it in the body tag
{{#each tasks}}
<ol> <li>Router Name: {{ routerName }}</li>
<li>Router Enable: {{Enable}}</li></ol>
{{/each}}
However, when I wrap it within a template and try call it via a route (iron router), it fails to show the query result.
<template name ='ManagementConfig'
{{#each tasks}}
<ol> <li>Router Name: {{ routerName }}</li>
<li>Router Enable: {{Enable}}</li></ol>
{{/each}}
</template>
Route.js:
Router.route('/ManagementConfig',{ name:'ManagementConfig' });
Everything apart from the above works well within the template and the route. Where am I going wrong?
Your ManagementConfig template don't have access to tasks object. You can fix this by creating a helper method and passing the data.
Template. ManagementConfig.helpers({
'tasks': function(){
//Change this to your task data
return Lists.find({}, {sort: {name: 1}});
}
});

Parameter isn't passed into nested template

I'm doing category sidebar template for online shop. I will use that in 2 places - on customer, and admin side. Each one will have own service of clicking on category. I want to pass parameter "redirect" which will decide what action will be done, but the problem is, that parameter isn't visible in nested templates - only in 1st level categories.
HTML :
<template name="categoriesSidebar">
<ul>
{{#each mainCategories}}
<li>
{{> categoriesSidebarItem redirect=true data=this }}
</li>
{{/each}}
</ul>
</template>
<template name="categoriesSidebarItem">
<a href="#">
{{data.name}}
</a>
{{#if data.subCategories.length}}
<ul>
{{#each subCats }}
<li>
{{> categoriesSidebarItem redirect=redirect data=this }}
</li>
{{/each}}
</ul>
{{/if}}
</template>
Javascript :
Template.categoriesSidebar.helpers({
mainCategories: function() {
return Categories.find({'categoryLevel' : 1});
}
});
Template.categoriesSidebarItem.helpers({
subCats : function(){
return Categories.find({_id:{$in: this.data.subCategories}});
}
});
Template.categoriesSidebarItem.events({
'click a' : function(event){
if(this.redirect == true){
Router.go('category',{_id : this.data._id});
return false;
}else{
//categoryId is ReactiveVar used in another template
categoryId.set(this.category._id);
}
}
})
Result :
Women
Nike
Men
Nike
Adidas
Women and Men category work well , after clicking on them, "redirect" is seen as true and Router redirects to desired route, but for nested categories, "redirect" parameter is undefined.
How to pass that parameter to nested template ?
Change the code to this:
{{#if data.subCategories.length}}
<ul>
{{#each subCats }}
<li>
{{> categoriesSidebarItem redirect=../redirect data=this }}
</li>
{{/each}}
</ul>
{{/if}}
The each block changes the data context, so you need to retrieve redirect from the parent data context. That's what ../ does.

How to add a specific sidebar to meteor route?

For example I have an admin area and I want to display a specific sidebar for admin navigation
<body>
{{#if adminRoute}}
{{> sidebarAdminNav }}
{{> yeld }}
{{else}}
{{> yeld }}
{{/if}
</body>
I guess what you are looking for are called nested views. This answer gives the best option I have used so far. It is no "angular ui-router" ideal, but it does the job. In your layout:
{{#if layout.renderSidebar}}
{{> sidebarAdminNav }}
{{/if}}
{{> yield }}
And in each (sadly) of your admin routes:
data: function() {
return {
layout: {renderSidebar: true},
...
};
}
Some packages are available for sidebars in meteor.
https://atmospherejs.com/jelena/meteor-sidebar-transitions
https://github.com/awatson1978/semantic-ui-sidebar

Meteor Autoform method not called when nested in dynamic template

I'm having trouble understanding why AutoForm is not working 100% here. The client-side validation works but submitting the form is not calling the meteor method insertQuestion.
As soon as I replace the contents of the modal template with the modalQuestion template it works and the meteor method is called. So my best guess here is that it has got something to do with {{> Template.dynamic }} include but haven't been able to solve this problem myself.
Can anyone tell me why the dynamic template include is not playing nice here?
layout.html
<template name="layout">
{{> modal}}
</template>
layout.js
Session.set('modalData', {template: "modalQuestion", title: "Test"});
modal.js
Template.modalBlock.onRendered(function () {
this.autorun(function() {
if (Session.get('modalData')) {
$('#modal').modal();
}
});
});
modal.html
<!-- A template to include in index.html that dynamically renders the a modal template -->
<template name="modal">
{{#if modalData}}
{{> Template.dynamic template=modalData.template data=modalData}}
{{/if}}
</template>
<!-- A generic block to be used by our modals -->
<template name="modalBlock">
<div id="modal">
<header>{{title}}</header>
{{> Template.contentBlock }}
</div>
</template>
<!-- A specific modal template -->
<template name="modalQuestion">
{{#modalBlock title=title}}
{{ #autoForm schema=SchemasQuestion meteormethod="insertQuestion" type="method" id="insertQuestionForm" class="form" }}
{{> afQuickField name="text" label=false placeholder="schemaLabel" }}
<button type="submit" class="button">Submit</button>
{{ /autoForm }}
{{/modalBlock}}
</template>

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>

Resources