May I ask a stupid question? I have a form having select list that needs to have data from MongoDB. First I try to get data from MongoDB (I use Mongoose), save it to array, and then render to view to populate to HTML Select.
File Task.js
exports.createForm = function (req, res) {
var creators = [];
CreatorModel.find({}).populate('id name').exec(function(err, crts) {
console.log("Creators:", crts);
creators = crts;
});
res.render('tasks/create-form', {
creators: creators
});
};
File Template
<p>
Creator:
<select id="creatorlist" name="creator">
{{#each creators}}
<option value="{{id}}">{{name}}</option>
{{else}}
<option value="">No creators</option>
{{/each}}
</select>
<a href="/creator/new">New Creator</a>
</p>
But If I embed render function into callback, it works
CreatorModel.find({}, function(err, creators) {
AssigneeModel.find({}, function(err, assignees) {
res.render('tasks/create-form', {
creators: creators,
assignees: assignees
});
});
});
But I find that it's not OK, because later I have to display exactly value from task ID and quite difficult to improve code
THen I modify my code a little bit
var creators = {};
CreatorModel.find({}).exec(function(err, crts) {
console.log("Type:", typeof(crts));
creators = crts;
console.log("Creators:", creators);
});
console.log("Creators 2:", creators);
I check in console log and find that "Creators 2" printed first
Creators 2: {}
Type: object
Creators: [ { name: 'Jen Smith', _id: 51d3ec2933a3c53c57000001, __v: 0 },
{ name: 'Paul Scholes', _id: 51d3ec3933a3c53c57000002, __v: 0 } ]
It seems that Mongoose find() run asyn..
The problem with assigning to array is I can not convert json document obj to array in callback function? Are there other ways to populate date from MongoDb to HTML Select Tag ?
I don't quite understand your question completely since the question has many parts but it seems like you're trying to avoid asynchronous paradigm. You can wait for mongoose objects to be populated before rendering them with template.
You can either force async behavior in node
https://github.com/caolan/async#parallel
async.parallel([
function(callback){
CreatorModel.find({}).exec(function(err, crts) {
creators = crts;
callback(creators);
});
} ], // optional callback
function(err, creators){
res.render('tasks/create-form', {
creators: creators,
assignees: assignees
});
}
Or use QueryStream to pipe it to res.render
http://mongoosejs.com/docs/api.html#querystream_QueryStream
Later on, you can perform Array#map to transform array to Hash.