Meteor: Accessing another collection with an id in an #each block - javascript

So I have two collections, appliers & profiles,
appliers = {_id,idAppliersProfile}
&
profile = {_id,profilename}
So my question is if I do an #each for appliers, how do I access profile collection to get the profile instead of just the id?
Thanks.

Assuming both sets of docs are published to the client, one solution looks something like this:
html
<template name="myTemplate">
{{#each appliers}}
{{#with getProfile idAppliersProfile}}
<div>{{profilename}}</div>
{{/with}}
{{/each}}
</template>
js
Template.myTemplate.helpers({
appliers: function () {
return appliers.find();
},
getProfile: function (id) {
return profile.findOne(id);
}
});

Related

how to pass a parameter to meteor helper that returns an object

I'm wondering if it's possible to pass a parameter to a meteor helper and insert in HTML a property of the object returned, and not merely a final value returned. I have something like this:
HTML:
<Template name ="conversationList">
{{#each conversation}}
{{getName.userName convStarterId}} convStarterId its a property of conversation object
{{/each}}
</Template>
Helper:
Template.conversationList.helpers({
getName: function(Id){
return Members.findOne({userId:Id}) // the Object returned have a property userName},
conversation: function() { //return info from another collection
}
});
It seems the 3rd line of my html is not working...
This should make userName available in your template:
<template name="conversationList">
{{#each conversation}}
{{getName convStarterId}}
{{/each}}
</template>
Template.conversationList.helpers({
getName: function(Id){
return Members.findOne({userId:Id}).userName;
},
conversation: function() {
...
}
});

Add class to data received from Mongo based on a field value in Mongo, on a Meteor app

I got mongo collection documents which includes an array which includes bunch of other objects. This is for a simple chat app.
I access all the data within the document and display it. Nonetheless, I have difficulties to give my-message class to my messages. When I write this below code, it gives all messages my-message class. :/
So what am I doing wrong?
Object Structure:
{
_id: "RCe9ZBS9PfkwrqKvg"
borrowerId: "Rg33iLJyRYqHyMpk4"
messages: Array[{text:messageBody, from:currentUserId, date:New Date()}]
ownerId: "fPv5yWJiSqFX3bAhR"
reqId: "KXErmpFJ7LiCbKsqc"
}
Template:
{{#with getMessages}}
{{#each messages}}
<p class="{{#if myMessages}} my-message {{/if}}">{{text}}</p>
{{/each}}
{{/with}}
Helper:
Template.reqMessages.helpers({
getMessages: function () {
var theReqId = FlowRouter.getParam("reqId");
return Messages.findOne({reqId: theReqId});
},
myMessages: function () {
var currentUserId = Meteor.userId();
var theReqId = FlowRouter.getParam("reqId");
return Messages.find({reqId: theReqId,
messages: [{$elemMatch: {
from: currentUserId
}}]});
}
});
I think you mean to do this:
{{#with getMessages}}
{{#each messages}}
<p class="{{#if isMine}}my-message{{/if}}">{{text}}</p>
{{/each}}
{{/with}}
Template.reqMessages.helpers({
getMessages: function () {
var theReqId = FlowRouter.getParam("reqId");
return Messages.findOne({reqId: theReqId});
},
isMine: function () {
return this.from === Meteor.userId();
}
});
Since you are already looping through the messages array in your template, the helper's context (this) is each object in the array. You can determine if it is from the user by simply comparing this.from and Meteor.userId().

pathFor cannot find route - Iron Router & Meteor

Iron Router cannot find a path that I'm pretty sure is defined correctly. The path name shows up as valid and exists in my meteor shell, but it returns as "undefined" in my Chrome console. Here's the template declaration:
<template name="vidPreview">
<div class="videoPreview">
<h2>{{title}}</h2>
Play
<p>Created At: {{createdAt}}</p>
{{#if isLive}}
<p>LIVE</p>
{{/if}}
<p>Viewers: {{uniqueViewers}}</p>
<p>Views: {{views}}</p>
<p>Location: {{location}}</p>
<ul>
{{#each genres}}
<li><p>{{this}}</p></li>
{{/each}}
</ul>
<p>Created by: {{creator}}</p>
</div>
</template>
And here's the route declaration:
Router.route('/video/:_id',{
name: 'singleVideo',
template: 'singleVideo',
layoutTemplate: 'singleVideo',
data: function(){
var currentVideo = this.params._id;
return Videos.findOne({ _id: currentVideo });
},
action: function(){
this.render('singleVideo');
}
});
There are no helpers operating on the vidPreview template. The data context is that of an individual Video object, and this template gets placed multiple times into a parent template. Help is greatly appreciated.
I thought the route name parameter in pathFor was positional, i.e.
{{pathFor 'singleVideo' _id=this._id }}
"We can pass data, query and hash options to the pathFor helper."
Try:
{{pathFor route='singleVideo' data={ _id: this._id} }}

Meteor JS: How to use Spacebars to display contents inside an array retrieved from Meteor Collection

I have a collection:
MenuItems = new Mongo.Collection('menu_items');
and I also have an array:
var arrayToInsert = ['Gemstone', 'Rings'];
I then insert this array into the collection via:
MenuItems.insert(arrayToInsert);
The resulting document inside my mongodb as shown in RoboMongo is:
{
"_id" : "yRXmFGxLCZXLf9Ynh",
"0" : "Gemstone",
"1" : "Rings"
}
In my Template Helper I have:
menuItems: function(){
return MenuItems.find();
},
In my .html file I do this:
{{#each menuItems}}
{{this}}
{{/each}}
But I only get this output:
[object Object]
How do I use Spacebars to iterate through this array of data so I may get it to display 'Gemstone' and 'Rings'????
Thank you very much.
If you want the array to represent the menu items value, you should insert them into the collection like this :
arrayToInsert.forEach(function(menuItem){
MenuItems.insert({
label: menuItem
});
});
Then you can display the menu items in your template :
JS
Template.menu.helpers(function(){
menuItems: function(){
return MenuItems.find();
}
});
HTML
<template name="menu">
<ul>
{{#each menuItems}}
<li>{{label}}</li>
{{/each}}
</ul>
</template>
If you want to store the array as part of the collection documents, use this code :
JS
MenuItems.insert({
items:arrayToInsert
});
HTML
<template name="menu">
{{#each menuItems}}
<ul>
{{#each items}}
<li>{{this}}</li>
{{/each}}
</ul>
{{/each}}
</template>

How to fetch data from collections when the route/template consist on more than collection?

Example:
routes.js:
this.route("chapterPage", {
path: "/books/:bookId/chapters/:_id",
data: function() {
var chapter = Chapters.findOne(this.params._id);
var book = Books.findOne(this.params.bookId);
var chapters = Chapters.find({
bookId: this.params.bookId
}, {
sort: {
position: 1
}
});
return {
chapter: chapter,
book: book,
chapters: chapters
};
}
});
As you can see this template/route has two collections Book and Chapter. Previously, I used to call the collections individually like this:
chapter_form.js:
Template.chapterForm.events({
"input #input-content": function() {
var currentChapter = Session.get("currentChapter");
Chapters.update(currentChapter, {
$set: {
content: $("#input-content").html();
}
});
}
});
But now in my new route/template I can't do that since it isn't based on any collection:
chapter_page.js:
Template.chapterPage.events({
"input #input-content": function() {
console.log(chapter._id); // this returns is not defined
console.log(this._id); // this one too
}
});
How to get around this?
EDIT:
I also tried calling the chapter_form.html template:
<template name="chapterPage">
{{> chapterForm}}
</template>
But it doesn't display and shows stuff like: Cannot read property 'content' of undefined so it isn't recognizing the template.
There are two problems in your code.
First in the data function of the chapterPage route, you do not return the object containing your data.
// no return here in your question, need to do :
return {
chapter: chapter,
book: book,
chapters: chapters
};
Then in your event handler, you can access the data context using this, so the correct syntax to access the chapter or book id is this.chapter._id or this.book._id.
EDIT :
Inside templates route helpers and event handlers, this refers to the current data context assigned to the template.
There are several ways to assign a data context to a template.
You can use attribute="value" syntax along with template inclusion syntax.
{{> myTemplate param1="value1" param2="value2"}}
Template.myTemplate.helpers({
paramsJoined:function(){
return [this.param1,this.param2].join(",");
}
});
You may also use a helper value coming from the parent template data context :
<template name="parent">
{{> myTemplate someHelper}}
</template>
Template.parent.helpers({
someHelper:function(){
return {
param1:"value1",
param2:"value2"
};
}
});
If you don't specify a data context when using the template inclusion syntax, it is assumed to be inherited from the parent data context.
You can also use {{UI.dynamic}} (http://docs.meteor.com/#ui_dynamic) to specify a dynamic template name along with a dynamic data context.
{{> UI.dynamic template=Router.template data=Router.data}}
This is this kind of approach that iron:router is using to set dynamically the route data context of the route template (implementation is slightly more complex though).
Meteor provides utilities to access current data contexts as well as parent data contexts, which can be useful :
http://docs.meteor.com/#template_currentdata
http://docs.meteor.com/#template_parentdata

Categories

Resources