Meteor: There is no route for the path error. how to access SINGLE article within a nested object - meteor

I have an array of 10 objects 'categories' and each category has sub objects such as posts within that category. This is how it looks.
I access the category list like this.
<template name="CategoriesMain">
{{#each articles}}
<li>
<h2>{{name}}</h2>
</li>
{{/each}}
</ul>
</template>
this link
<h2>{{name}}</h2>
accesses the 'posts' list within the category which looks like this
<template name="CategoriesSingle">
<h1>This is a test</h1>
<ul>
{{#each articles}}
{{#each posts}}
<li>
<h2>{{title}}</h2>
</li>
{{/each}}
{{/each}}
</ul>
</template>
this link is supposed to target the SINGLE POST from the post list within the category
<h2>{{title}}</h2>
PROBLEM:
I get the error: There is no route for the path: /catsingle/ when ever i try to access the SINGLE POST
even though i have it in my routes.js like this
FlowRouter.route('/catsingle/:_id', {
name: 'catsingle',
action() {
BlazeLayout.render("AppLayout", {main: "CategoryArticleSingle"});
}
});
the template helper looks like this
Template.CategoryArticleSingle.helpers({
articles: function () {
var id = FlowRouter.getParam('_id')
return CategoryCollection.findOne({_id: id});
}
});
How can I successfully the single post within a category?

Your posts array doesn't have an _id key, it has an ID key.
Try:
<h2>{{title}}</h2>

Related

How to Access URL Parameter from Template File in Meteor?

I am using Iron Router, and I want to get the parameter from a URL and place it in my template file. For example:
http://localhost:3000/categories/electronics
In my template file:
<template name="category_products">
<p>Sorry, there are no _____ products.</p>
</template>
I want to replace _____ with electronics so the output will be
Sorry, there are no electronics products.
Assuming you've defined a route, you can get the parameters using this.params. You can also provide template with a data context that is an object that includes multiple keys:
Router.route('/categories/:name',()=>{
this.render('category_products', {
data: function () {
return {
cursor: Products.find({categoryName: this.params.name}),
category: this.params.name
};
}
});
});
html:
<template name="category_products">
{{#if cursor.count()}}
{{#each cursor}}
{{name}}
{{/each}}
{{else}}
<p>Sorry, there are no {{category}} products.</p>
{{/endif}}
</template>

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.

How to fetch query parameters in a template?

I am using Meteor 1.2.1 + iron-router with autopublish turned on
I would like to construct an anchor href based on collection values returned by a helper and query params
Is it possible to do this in the template tag, e.g. query_param1 should be read from the URL?
<template name="dataEntry">
{{#each data}}
<li>
<a href="/listing?name={{name}}&color=<query_param1>">
Data name
</a>
</li>
{{/each}}
</template>
Above, {{name}} is returned by the collection and query parameters are appended to that to create a full hyperlink for the href.
You can use #Stephen's suggestion like this.
In your template html,
<template name="dataEntry">
{{#each data}}
<li>
<a href="/listing?{{queryParams}}">
Data name
</a>
</li>
{{/each}}
</template>
In your template JS,
Template.dataEntry.helpers({
"queryParams": function () {
var name = "";
//get name from collection here like...
//name = Meteor.user().profile.firstName;
var color = Router.current().params.color;
return "name=" + name + "&color=" + color;
}
});
Or you can use two separate helpers
In your template html,
<template name="dataEntry">
{{#each data}}
<li>
<a href="/listing?name={{name}}&color={{color}}">
Data name
</a>
</li>
{{/each}}
</template>
In your template JS,
Template.dataEntry.helpers({
"name": function () {
var name = "";
//get name from collection here like...
//name = Meteor.user().profile.firstName;
return name;
},
"color": function () {
return Router.current().params.color;
}
});
You can access an IronRouter param through a helper, e.g.:
Router.current().params.query_param1

Meteor: Spacebars each parameter

I'm new to Meteor.js and have run into a problem.
I am passing in a user object to a profile template e.g.:
{
_id: "D8JpXRQskm3grykjg",
username: "foo",
profile: {communities: ["AkGCakz6mSgMb8qyS", "j8aB3i5iscrC4ehkA"]},
}
<template name="profile">
<h1> {{username}}: {{_id}} </h1>
<h3>Communities</h3>
<hr>
{{#each profile.communities}}
{{> communityItem}}
{{/each}}
</template>
The problem is I've already written a communityItem template that I am using elsewhere which accepts the communityName. Is there a way that I can write a helper function, passing in the communityIds list that would return a list of community names? I would like:
...
{{#each getCommunityNames(profile.communities)}}
{{> communityItem}}
{{/each}}
...
I could very well be approaching the problem the wrong way or not writing in a "Spacebars" fashion. Thanks!
sure you can:
Template.myTemplate.helpers({
getCommunityNames: function(commIds) {
var communities = Communities.find({_id: {$in: commIds}}).fetch();
return _.pluck(communities, 'name'); // returns ['Name 1', 'Name 2'];
}
});
Note, the syntax method param not method(param)
{{#each getCommunityNames profile.communities}}
{{>communityItem}}
{{/each}}

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.

Resources