Meteor .find() from Collection returns [object Object] - mongodb

Running on Ubuntu
Data.js
//Collections
Database = new Meteor.Collection('data');
if (Meteor.isClient) {
Template.main.data = function () {
var c = Database.find();
return c;
};
}
if (Meteor.isServer) {
Meteor.startup(function () {
// code to run on server at startup
});
}
data.html
<head>
<title>data</title>
</head>
<body>
{{> main}}
</body>
<template name="main">
{{data}}
</template>
I inserted into the db using mongo:
> db.Database.insert({title: 'ShouldWork'});
> db.Database.find();
{ "_id" : ObjectId("5296403855ee6e1350b35afb"), "title" : "ShouldWork" }
Yet when I run the site it just returns [object Object]..
There should be autopublish on and insecure,
This has become quite the roadblock for me to clear in learning the framework.

This is expected. This is because the results of .find() are always a cursor and have multiple objects.
You have to decide which one you want or if you want to loop through each one.
1) You want to use one result:
var c = Database.findOne();
or 2) You want to iterate through each one:
{{#each data}}
{{title}}
{{/each}}
Additionally be sure to use the property of {{data}} because {{data}}, even with findOne is still an [Object object]. You should use something like {{data.title}} instead depending on the property you want to use.

How to access data in Mongo DB from html ?
First of all you need to have the Mongo DB instance present in global variable i:e it must be declared in any .js file as below. It is not part of client or server code
Say we create a Collection of Events in one of the js files.
EventList = new Mongo.Collection('Events');
Now, in order to access all the objects from HTML, we would need a Helper function inside client in our .js file. Below is Helper used:-
Template.viewEvent.helpers ({
//NOTE : 'event' is the name of variable from html template
'event' : function () {
//returns list of Objects for all Events
return EventList.find().fetch();
}
'users' : function () {
//returns reference to Document for all users
return UserList.find().fetch();
}
});
Just left to Display content on .html:-
Say EventList Collection has fields Event_Name, Event_Date. Below would be the html template code
<template name="viewEvent">
<h2>View Event</h2>
<!-- Iterate on all Objects fetched by the Helper Class-->
{{#each event}}
{{Event_Name}} : {{Event_Date}}
{{/each}}

Related

Why is my select not being populated with my MongoDB Collection?

In my Meteor app, I am publishing:
ForeignVisaTypes = new Mongo.Collection("foreignVisaTypes");
if (Meteor.isServer) {
Meteor.publish("foreignVisaTypes", function () {
return ForeignVisaTypes.find();
});
}
...and subscribing to:
if (Meteor.isClient) {
Meteor.subscribe("foreignVisaTypes");
. . .
}
...a Collection which is populated with values.
However, this attempt to populate the select is failing:
<select name="selvisatype" id="selvisatype" title="Please select a visa type">
{{#each foreignVisaTypes}}
<option value={{value}}>{{display}}</option>
{{/each}}
</select>
Why is it failing?
It's not enough to subscribe to a collection. It will not be available directly in spacebars as a helper. So you still need to define a helper to expose it.
Just add this to your client code and things should start working (replace myTemplate with the name of your template):
Template.myTemplate.helpers({
foreignVisaTypes: function() {
return ForeignVisaTypes.find();
}
});

MeteorJS: Autoform + CollectionFS, associating images from an FS.Collection with Corresponding Mongo.Collection Document?

I'm building a very small Meteor application simply to get a better understanding of Autoform and CollectionFS, and their use together. I currently have everything set up with the following packages:
iron:router, aldeed:autoform, aldeed:collection2, cfs:standard-packages,
cfs:filesystem, cfs:autoform
I have a sample Mongo Collection assigned to "Books" set up with a SimpleSchema attached, with fields from the demo like title and author. The corresponding code for the file upload is:
fileId: {
type: String,
autoform: {
afFieldInput: {
type: "cfs-file",
collection: "images"
}
}
}
The FS.Collection code is:
Images = new FS.Collection("images", {
stores: [new FS.Store.FileSystem("images", {path: "~/uploads"})]
});
This is in conjunction to a quickform: {{> quickForm collection="Books" id="insertBookForm" type="insert"}}
The insert is fine, and I can iterate over the documents and display the various fields using spacebars and a helper function called "books", like so:
{{#each books}}
<li>{{title}} by {{author}}</li>
{{/each}}
I can also iterate over images uploaded to the FS.Collection with a helper returning the entire collection called "files," and looping over them like so:
{{#each files}}
<img src="{{this.url}}" />
{{/each}}
The issue I'm having is linking the two together. I want to be able to do something along the lines of:
{{#each books}}
<li>{{title}}, by {{author}} <img src="The-Corresponding-Image}}" /></li>
{{/each}}
Obviously not that exact layout, but I basically just want to be able to print images with their corresponding titles and authors to be able to use autoform with collectionfs for my needs.
I'm stuck trying to retrieve the fileId from a specific document in the Books collection, and then plugging that into an Images.findOne({fileId: fileId}) and linking the two together.
Can anyone point me in the right direction?
I was able to figure it out thanks to Ethaan's guidance. What I had to do was the following:
Autoform Hook:
AutoForm.hooks({
insertBookForm: {
after: {
insert: function(error, result, template) {
insertedFile = Books.findOne(result).fileId;
Images.update({_id: insertedFile}, {$set: {'book': result}});
}
}
}
});
I set a field of 'book' to the _id of the document being inserted (stored in the result parameter) right after it was inserted.
This is my corresponding HTML:
{{#each books}}
<li>{{title}} by {{author}}</li>
{{#with files}}
<img src="{{this.url}}" />
{{/with}}
{{/each}}
And my helpers:
Template.layout.helpers({
books: function () {
return Books.find({});
},
files: function() {
return Images.findOne({book: this._id});
}
});

Selecting attributes from an object when using find() in MongoDB/Meteor

So I'm new to Meteor, and have been playing around with it, but have hit a few issues with moving over to Mongo.
Below is a simple example, where I have inserted some documents into my collection, but cannot seem to extract the attributes properly.
Here is my code (and my result vs expected result is below it)
vizart.js
ContentPieces = new Mongo.Collection("content");
if (Meteor.isClient) {
Template.loggedInDash.helpers({
content: function () {
return ContentPieces.find({});
}
});
}
vizart.html
<template name="loggedInDash">
{{#if currentUser}}
<p>Here is the content you've created</p>
<ul>
{{#each content}}
<li>{{content}}</li>
{{/each}}
</ul>
{{/if}}
</template>
Result (just pasted from the app in my browser)
Here is the content you've created
[object Object]
[object Object]
[object Object]
Expected
As you can see, I am not 100% sure how to pull out an attribute. For example, each document has a name attribute, and I'd like to spit that out in the list instead. Any help or guidance on how to select the name attribute from the content collection?
Thanks in advance!
The meteor template language (spacebars) is inspired by handlebars. I'd recommend having a look at both sets of docs, but the handlebars documentation will get you up to speed with the basic syntax.
In your example, if each document in ContentPieces has a name then you can add it to your list like this:
<ul>
{{#each content}}
<li>{{name}}</li>
{{/each}}
</ul>
I'd also recommend having a look at this post to better understand template data contexts.
In your process you are displaying the whole document, if you just want to display the name attribute you can do it by
if (Meteor.isClient) {
Template.loggedInDash.helpers({
content: function () {
var name=ContentPieces.find({}).name;
if(name)
return name;
}
});
You can just pass the field name that you want to display

Meteor how to retrieve an array of questions from the mongo db and displaying just one of them within the app

As I am new to programming and Meteor I am currently building a (simple) Quizz app using Meteor.js. I followed the discover Meteor Guide book and rebuilding their example microscope project into a quiz. I am currently struggling with retrieving the array of questions from the mongo db and displaying just one of them within the app.
The data within my collection currently looks like this:
Quizzes.insert(
{"quiztitle": "Quiz One",
"quizquestions": ["Q1.1", "Q1.2"]
}),
I am currently displaying all of them thorugh
<template name="quizPage">
<h3>
{{#each quizquestions}}
{{> quizQuestion}}
{{/each}}
</h3>
and
<template name="quizQuestion">
<div class="quiz">
<div class="quiz-content">
{{this}}
</div>
</div>
I have tried several solutions already to getting only the first question to display:
1.Substituting the array number through a helper function with Spacebars. Although the helper worked (it returned a specific number for instance 0), and the array by itself ( 0 between brackets). Meteor does not seem to allow spacebar inserts into array brackets.
<template name="quizQuestion">
<div class="quiz">
<div class="quiz-content">
{{quizquestions.[{{questionnumber}}]}}
</div>
</div>
2.aReturning a specific field through a mongodb query. for example
Return Quizzes.find( { quiztitle: 'Quiz One' }, { quizquestion: 1, _id:0, quiztitle: 0 });
Unfortunately this is only allowed on the server side. I have also tried to save the array resulting from the return into a global variable within the lib folder
questionArray = Quizzes.find( { quiztitle: 'Quiz One' }, { quizquestion: 1, _id:0, quiztitle: 0 } );
This is also the case when I try slicing the collection, which is suggested in a different post
3.As this also does not seem to work I have tried publishing a subset of the collection for use in a specific quiz. The problem I have here is that the collection seems to be published in its entirety. I publish the collection on the frontpage.js through
Meteor.subscribe('quizzes');
I have also tried subscribing within an autorun as is suggested in the documentation at http://docs.meteor.com/#meteor_subscribe
Deps.autorun(function () {
Meteor.subscribe("quizzes")});
Question: Could you help me find a way to return only the questions array and either save it to a global variable or return it through a helper. I hope you can help me out, thanks a lot,
Meteor Beginner.
First, you need to make sure the data is available on the client. In chrome, open up your javascript console (cmd+option+j) and paste Quizzes.find().fetch() and you should see your objects. Assuming that is good, continue...
To get your questions to display, you can return the specific question to a {{#with}} block like this:
{{#with question}}
<li>{{this}}</li>
{{/with}}
Your question helper could look something like this...
Template.TEMPLATE_NAME.helpers({
question: function(){
var currentQuestion = Session.get('currentQuestion') || 0;
return Quizzes.findOne({}).quizquestions[currentQuestion]
}
});
Then you can increment the Session variable each time you answer or go to the next question in a Meteor event, something like this:
Template.TEMP_NAME.events({
'click .next-question': function(){
var num = Session.get('currentQuestion') + 1;
Session.set('currentQuestion', num);
}
});
This will cause the helper to rerun and your new question will be passed back to the {{#with}} block.
In the quizPage template, add a helper which finds a single question:
Template.quizPage.firstQuestion = function() {
return this.quizquestions[0];
}
Then use it:
<template name="quizPage">
<h3>
<!-- #with is like #each, but for a single item -->
{{#with firstQuestion}}
{{> quizQuestion}}
{{/with}}
</h3>
</template>

Meteorjs display referenced document field

I have the following scenario. There is a collection Suppliers and another Invited. Now Invited.supplier = Supplier._id (syntax might be wrong) Invited collection refers to Suppliers in One to Many fashion.
In my html , I have
<template name="mytemplate">
{{#each invited_list}}
{{supplier}}
{{f1}}
{{f2}}
{{/each}}
</template>
I have a helper function
Template.mytemplate.helpers({
invited_list : function(){
return Invited.find({"something"});
}
});
I would like to display {{Suppliers.name}} instead of _id in {{supplier}} in my invited_list . What are my options?
You could create a resolver function such as:
Template.mytemplate.helpers({
invited_list : function(){
return resolveSupplierToNames(Invited.find({"something"}).fetch());
}
});
function resolveSupplierToNames(invitedList) {
for (var i=0; i<invitedList.length; i++) {
invitedList[i].supplier = Suppliers.findOne({_id: invitedList[i].supplier}).name;
}
return invitedList;
}
There are generally two options with mongodb, one is the above (manual). The second is to use DBRefs. However I'm not sure meteor supports DBRefs completely yet. As suggested in the mongodb docs theres nothing wrong with doing it manually.
Update
Meteor has since introduced a transform function, you can do something similar like:
Template.mytemplate.helpers({
invited_list : function(){
return Invited.find({"something"},{transform:function(doc) {
doc.supplier_name = Suppliers.findOne({_id: doc.supplier_id}).name;
return doc;
});
}
});