I have a question I hope you can help with. Basically, I'm doing a query on a MongoDB collection and attempting to pass the results back to a jade view.
app.helpers({
clients: function(){
users.find({uid:req.session.uid}).toArray(function(err, post){
if(err){
console.log(err);
}else{
return post;
}
});
}
});
This is where I reference the helper object in the view
p #{clients}
Right now I'm just getting [object Object] as the value in the view. If I log the results, I'll get the expected document results but if I try to push it into an array or a var, I get the [object Object] result. Any ideas?
This won't work, because you use the following structure:
clients: function() {
(some code)(function() {
return variable;
});
}
The return variable; statement returns from the inner function. But you need to return variable from the outer function. So how to do this? Actually you can't. You should do the query in a view and store the result for example in request and then pass the request variable to the template. You cannot use asynchronous functions in helpers.
Another thing is that when you use a function in a helper, then in the template you should use
p #{ clients() }
because it is a function. Nevertheless it won't work in this case.
Related
I am trying to get a document from a collection, but it doesn't seem to be working.
when i use the find().fetch(), it returns only an empty array. my code is as follows.
var users = new Mongo.Collection("users");
console.log(users.find());
var userRecord = users.find().fetch();
var returnUserRecord = {};
if (userRecord.length >0){
returnUserRecord = {username:userRecord.username, loginHash:userRecord.loginHash};
console.log("if statement is not complete and the value of the return variable is");
console.log(returnUserRecord);
}
return returnUserRecord
I have checked the database directly and noticed that there is indeed a document in the collection with the command:
meteor mongo
if it makes any difference, all this code in the in the server js file, and is being called from from the client by: Meteor.Methods()/Meteor.call()
EDIT 1
i created another collections with new data from the client, and after selecting the correct database, and running the command:
meteor:PRIMARY> db.newCollection1.find()
i get:
{ "_id" : ObjectId("55d1fa4686ee75349cd73ffb"), "test1" : "asdasd", "test2" : "dsadsa", "test3" : "qweqwe" }
so this confirms that it is available in the database, but running the following in the client console, still doesnt return the result. (autopublish is installed. i tried removing autopublish and made the appropriate changes to subscribe to the table, but that didnt work either).
var coll = new Meteor.Collection('newCollection1');
coll.find().fetch()
this returned an empty array. i have also tried the same on the server.js code using:
meteor debug
but i am still getting an empty array. does anyone know what i might be doing wrong here?
SOLUTION
the solution for this was to create the collection variable in the Meteor object context. this way it can be accessed from the Meteor context.
i.e.
Meteor.coll = new Meteor.Collection('newCollection1');
Meteor.coll.find().fetch();
i hope this helps someone. depending on your code you may want to use a different context.
You don't wait for this subscription to complete, therefore you get empty array.
You should probably read this or this to better understand it.
The thing is you connect users variable to "users" collection, and when you call it, it isn't yet polluted with data (if you don't want to use subscription then maybe use helper - it's reactive so it will return proper value when subscrtiption is finished)
Did you subscribe your users collection somewhere?
if (Meteor.isServer) {
Meteor.publish("users", function(){
return Users.find({})
});
}
if (Meteor.isClient) {
Meteor.subscribe("users");
}
First of all some advice: you can not define a collection twice. If you call new Mongo.Collection("users") a second time you will get an error. Therefore, it should be a global variable an not inside a method.
What I can see in your code is that you are trying to use an array as if it were an object. userRecord.username wont work because userRecord has the value of the fetch() which returns an array.
You could either change your code to userRecord[0].username or loop over the results with forEach like so:
var users = new Mongo.Collection("users");
console.log(users.find());
users.find().forEach(function(singleUser){
console.log(EJSON.stringyfy(singleUser));
}
in order to return the first user, you would be better of using findOne which returns the first object in the result.
I have a simple factory below that request a json object with some location info. The requests works, I can see that the data is in the object. But somehow there is scope problem. I cannot access the properties of the locations object, even if I know that the object has the property and the correct array.
You can see in the code snippet below (if you look at the comments) that I cannot access some value of the object when trying to ouput to the console.
Any idea on what could be the problem?
.factory('Spots', function(){
return{
all: function($resource){
var locations;
var Locations = $resource('http://localhost\\:3000/locationsd/');
locations = Locations.get(function(){
console.log(locations.results[0].obj.name); // THIS WORKS -> gives me the name of the location
});
console.log(locations); // THIS WORKS -> log an object with a result array, etc.
console.log(locations.results[0].obj.name); // THIS DOESNT WORK -> TypeError: Cannot read property '0' of undefined
return locations;
}
}
})
This is due to it being async. To utilize $resource properly within a service, you should use promises.
.factory('Spots', function(){
return{
all: function($resource){
var Locations = $resource('http://localhost\\:3000/locationsd/');
return Locations.get().$promise.then(function(res){
return res;
});
}
}
})
Then when calling the function from your controller:
Spots.all().then(function(res){
//do stuff with res here
})
If you aren't aware of what promises are, read about them here: https://docs.angularjs.org/api/ng/service/$q
General idea is the resource promises that it will finish eventually, and when it's done, it'll call the function you pass into its then().
I am iterating through items in an object using the forEach method.
function scrapeRssFeedData(rssFeeds, cb){
rssFeeds.forEach(function(rssFeed){
rssFeed.property = 'value';
console.log(rssFeed.property);
console.log(rssFeed);
});
}
The value that is logged for rssFeed.property is, correctly 'value'.
However, when the rssFeed object itself is logged, the property is not visible.
The original rssFeeds object is built using a Mongoose model.
Why can I not see the property when logging the object? What can I do to fix it?
Update: Even this code is not working:
function scrapeRssFeedData(rssFeeds, cb){
rssFeeds[1]['property'] = 'value';
console.log(rssFeeds[1]);
}
The fact that this example doesn't work makes me believe almost certainly it's something to do with the object having been built by Mongoose. I want to be done with Mongoose though at this point of the program and want to start adding values to this object.
As I grew to suspect, it was due to it being an instance of a Mongoose document, as opposed to just a normal Javascript object.
I was able to find the solution here:
How do you turn a Mongoose document into a plain object?
And adding .lean() into the query chain, ie:
function getRssFeeds(status, cb){
if(status == 'on'){
RSSFeed
.find({})
.populate('endpoints')
.lean() // <-- Needed to be added
.exec(function (err, feeds) {
cb(null, feeds);
});
}
else if(status == 'off'){
cb({'status' : 'functionality', 'message': 'app is turned off'})
}
}
I want to get the id of a newly inserted docuement in the callback of meteor.collection.insert.
I insert the Doc as follows:
Meteor.call('createDoc', {
key1: value1,
key2: value2
})
The createDoc function looks like that:
Meteor.methods createDoc: (options) ->
incidents.insert
key1: options.value1
key2: options.value2
, callback(error, result)
callback = (error,result) ->
console.log result
The Documentation says:
callback Function
Optional. If present, called with an error object as the first argument and,
if no error,the _id as the second.
So I expect result to return the new id, but am getting a Reference Error saying that error and result are not defined. What am I getting wrong here? Any help is much apprecated.
You mostly have the right idea, but you're confusing a couple of things. Currently, your Meteor method isn't returning anything, because you're calling the insert asynchronously by providing a callback. Asynchronous method returns can be done, but it's a lot more complicated than you need for something this simple (checkout this excellent async guide for more info).
Instead of having a callback, you can use the insert method without a callback and assign that to a variable, like var incidentId = Incidents.insert({ ... }); -- return that.
Then, in the client-side callback for the Meteor.call, the result should be the _id.
From client side, your callback function result will return last inserted object id if you return from Meteor.methods.
Meteor.call('addURL', url, function (error, result) {
urlId = result;
});
Meteor.methods({
addURL : function(url) {
return URL.insert(url);
}
});
urlId has the id of last inserted object.
BenjaminRH is right about the easier, more likely way to do this. However, there are times when you need the server to do the work, and/or some who insist that is the only way to do database work even in meteor, and here's how your code would do that:
# server code
Meteor.methods createDoc: (options) ->
created = incidents.insert
key1: options.value1
key2: options.value2
created
# on client code
Meteor.call 'createDoc', info, (err, data) ->
if err
console.log JSON.stringify err,null,2
# DO SOMETHING BETTER!!
else
Session.set('added doc', data )
# and something reactive in waiting for session to have 'added doc'
I've just started working with Node.js so please forgive any stupidity!!! I'm trying to create a new application using Node.js. Im using the Express framework with a Postgresql database. The problem is that in my view, I wanted to to call a function. So I used a helper function that is called from my jade file. But because this function accesses the database, I tried to use callback inorder to make it work.
However, I can't seem to call a function from my jade template with the last argument as a function. The helper function worked fine when there was only one parameter being passed and it wasn't a callback function. But because the database query took a while, the the data was never displayed. But when I try to call a function with callback from my jade template, I get a syntax error.
My function call in my jade template:
#{ nameAndVersion(result.bu_entrep_id, function(error, result)) }
My helper function (It's simple because I was trying to get it to work):
exports.helpers= {
nameAndVersion: function(entid, callback) {
var x=1;
callback(null, x);
console.log(1);
}
};
My error:
500 SyntaxError: Unexpected token )
So, basically, I want to call a helper function from my jade template and have that function be a callback function.
You want to do :
Parse template
Retrieve data
Render template with data
Express templating is expected to do :
Retrieve data
Parse and render data
You should not have to execute complexe code once you've started rendering (what if you database is unavailable ?).
Jade helpers only have a formating purpose, not functionnal.
What you should do, instead of calling an helper, is giving the necessary data when calling the renderer.
app.get('anyPage', function(req, res) {
database.doSomeDataBaseQuery( /* Data base callback */ function(data, err) {
if(!err) res.render('pageTemplate', {dataBaseData:data});
}
});