Passing mongoose documents to view and use in script tag node.js - javascript

I have an app running in Node.js with Express, and I wanted to dinamically change options on select object with jquery. This is actually not a big problem, but I'm having troubles on using the res.render parameters (which are mongoose documents) in the script tag. I use them without any trouble on the html (jade actually), but in the script tag I get a problem with the ObjectId not being a String.
This is an extract of the code:
On the backend:
router.get("/new", function(req, res){
res.render("session/documentos/new",
{
services: res.locals.services
});
});
On the view
block content
div
h1(class="text-center") New document
form(id="newDoc" action="/session/documentos" method="POST")
div(class="tab") Service:
div(class="form-group")
select(class="form-control" name="svc" id="svc")
option(value="undefined" disabled selected) Choose one
for service in services
option(value=service._id)=service.name
script.
$(document).ready(function() {
var sessLenght = 0;
var selectedSvc = #{services};
$("#svc").change(function(){
console.log("Service changed: " + selectedSvc);
});
});
And this is the error I'm getting:
Console error
And in Sources:
Source error on ObjectId
So I'm being able to use with no troubles the "services" collection of documents, but when trying to use them on the script tag I'm getting problems with the ObjectId element.
I was thinking that one soution would be to convert to string the ObjectId when querying the database, but I think there might be a cleaner solution to that. Which might be the best way to solve the issue?
Any thoughts appreciated! Thanks in advance

Try to change var selectedSvc = #{services};
to var selectedSvc = !{services};
or var selectedSvc = !{JSON.stringify(services)};

Related

Display data from database (using mongodb) in hbs/html file Node.Js

I started studying node.js, and now I'm trying to do a "Todo-App".
I'm trying to find the best way to transfer data from my database (using mongodb) into my hbs files, so I could display it.
From the server.js -> server to the hbs -> client (correct to me if I'm wrong please, by assuming that server.js is the server of course and the hbs file is the client)
So, I succeeded to do it by passing an array.
but when I'm trying to display in html desing, it just looking bad.
The code:
app.get('/allTasks',(req,res)=>{ //get (go to) the allTasks (hbs file)
Todo.find().then((todos) => {
console.log(todos);
var arrayOfTodos = [];
todos.forEach(function(element){
console.log("\n\n\n\n\n elemnt details: ",element.text + "\n",element.completed+"\n");
arrayOfTodos.push(element.text,element.completed);
});
res.render("allTasks.hbs", {
pageTitle: "Your tasks: ",
todos: arrayOfTodos
});
});
});
The result is:
You can see a picture
As you can see, its just looking bad... cause it just display an array,
an I want to display each task seperately.
Any tips?
Thanks a lot,
Sagiv
Instead of using push just do:
Todo.find().toArray(function(err, result){
arrayOfTodos = result;
})
Once you have your array, the design got nothing to do with mongodb. You will need to learn how to use your render technology. You need to touch your html template, so you should start by posting that.
The problem solved.
I just had to learn how to handle the data in the hbs side.
so the code is: (in hbs)
{{#each todos}}
{{missionNumber}} <br>
{{text}}<br>
completed = {{completed}}<br><br>
{{/each}}
as you can see, the each is a loop , that pass on the todos parameter (my array)
and i just have to display the data in the way i want it to be displayed.
thanks for your help.

Send json to jade

I am sending a big json file from server to jade, but the " are replaced with: " therefor the json is unreadable/unparsable and I get this error:
Uncaught SyntaxError: Unexpected token &
I send the data like this from node:
res.render(view, {world:{name:"SomeName",width:50},otherdata:{...}});
and then get it in jade like this:
doStuff(JSON.parse(#{data}));
and here it is unreadable data which looks like:
{world:{name:"SomeName",width:50...
can I somehow disable the conversion of the quotes?
Server side within your rout you will do the following consider the object user
var user = {username:"myname"};
res.locals.user = user ;
response will be :
res.render('view');
jade view will have the variable available :
if user
script(type='text/javascript').
var user = !{JSON.stringify(user)};
Try adding app.use(bodyParser.json()); if you still have the issue
hope that helps
No experience with jade but from the language reference (http://jade-lang.com/reference/interpolation/) i guess
doStuff(JSON.parse(!{data}))
might work

Serve dynamic javascript file with nodejs

Questions
How to serve javascript file dynamically? Specifically, the scripts maintain most of its body but with some variables changable (imagine HTML Jade template, but this is for pure javascript).
Scenario
When user or browser (http GET in general) visits /file.js passing parameter api, e.g. /file.js?api=123456, I would like to output pure javascript where I can take that 123456 and put in inside of my code, dynamically. Content-Type is application/javascript.
Sample:
var api = #{req.query.api}; //Pseudo
//The rest of my javascripts template
...
From my main .js file, I have set up the route:
app.get( '/file.js', function( req, res ) {
//Pseudo code that I would like to achieve
var name = req.query.name;
res.render( 'out_put_javascript_file_from_jade_file.jade', { name: name } );
});
So when a person visits /file.js, the script file will be rendered differently based on the parameter api passed in the URL. The only possible dynamic way I can think of is using Jade, but it doesn't allow pure javascript template. I believe there must be other solutions.
Please excuse my explanation. The problem is somewhat like this: How to generate a pure JavaScript file with Jade
If you want to do something quick and dirty, then you can do something like this (based on your example in the comments).
App init - read the .js template file and cache it:
// this should be async, but hey, not teaching you that part here yet
var fileJs = fs.readFileSync('file.js.template');
File.js:
(function() {
$(window).on('load', function() {
alert('Your api key is API_KEY_CONST');
});
})();
Request:
GET /api/file.js?key=123
Router:
app.get('/api/file.js', function(req, res) {
var key = req.query.key;
var key = fetchKeyFromDBSync(); // just to make it easier here, no async.
var out = fileJs.replace(API_KEY_CONST, key);
res.setHeader('content-type', 'text/javascript');
res.write(out);
res.end();
});
Now, this is really dumb and you should not try it at home, but it simply demonstrates how to do what you wanted.
Edit:
Depending on the file length, you might perform a bit better if you put the chunks of the file into an array, like:
var fileChunks = ['(function(){ blablabla;', 'var myAPIKey=', 'KEY_PLACEHOLDER', '; alert (myAPIKey);', '})()']
So later when you're resolving it with the real API key, you join the file.
fileChunks[2] = '12345';
var responseData = fileChunks.join('');
res.write(responseData);
But your last-accessed api key is then held in an array. Not quite future proof, but it shouls work if you need something quick.

How do I post an HTML class into a mongoDB collection using express/mongoose and client-side JS?

First off my programming knowledge is entirely on the front-end, but I'm experimenting with node, express, mongoose, and mongodb. I'm using someone else's template to try and build an app the right way, but I'm lost when connecting the dots. I have the following jade:
form(method='post', action="/post/comment/" + post.id)
textarea(name='text')
input(type='submit', value='Save')
Combined with this from the routes/posts.js file
app.post("/post/comment/:id", loggedIn, function (req, res, next) {
var id = req.param('id');
var text = req.param('text');
var author = req.session.user;
Comment.create({
post: id
, text: text
, author: author
}, function (err, comment) {
if (err) return next(err);
res.redirect("/post/" + id);
});
});
and this is models/comment.js :
var mongoose = require('mongoose');
var ObjectId = mongoose.Schema.Types.ObjectId;
var createdDate = require('../plugins/createdDate');
var schema = mongoose.Schema({
text: { type: String, trim: true, validate: validateText }
, post: { type: ObjectId, index: true }
, author: String
})
function validateText (str) {
return str.length < 250;
}
schema.plugin(createdDate);
module.exports = mongoose.model('Comment', schema);
Now this works fine, for submitting a comment and saving it in the DB. Problem is, is that I don't want to save a comment, but HTML after a function has manipulated it. So I tried:
var everything = $('.whatever').html();
$.post("/post/comment/:id", everything,
function(){
console.log('html saved!')
}
)
But I got a POST http://localhost:3000/post/comment/:id 500 (Internal Server Error) Now I'm aware that I probably don't have the id variable so I tried pasting in the number that is in the url, and that seemed to go through without error, but than didn't show up in the DB. I'm aware that this may not be a specific question, and that I may be going about this entirely wrong but any general direction would be much appreciated. Thanks.
You seem to have a number of problems here. Try taking a look at the following:
Your router is set to receive posts to "/post/comment/:id", but your post in the last code block is posting to "/post/comments/:id", where comments is plural. This will likely result in a 404. (Check the networks tab of your browser javascript console. It may be silently failing without you realizing it).
Your 500 error is likely coming from the fact that you directly posted ":id", instead of an actual identifier. Many node apps will have an app.param() block set up to validate these parameters, and your friend's template is likely breaking when it doesn't get a number it expects.
The data that you post must match the schema of the model you're saving it to. Any keys that aren't named in the schema will be stripped prior to saving, and in your case, if no keys match, it will just be a default comment instance, and won't save at all.
Hope that helps!

Couchbase Java API and javascript view not returning value for a specific Key

I am using couchbase API in java
View view = client.getView("dev_1", "view1");
Query query = new Query();
query.setIncludeDocs(true);
query.setKey(this.Key);
ViewResponse res=client.query(view, query);
for(ViewRow row: res)
{
// Print out some infos about the document
a=a+" "+row.getKey()+" : "+row.getValue()+"<br/>";
}
return a;
and the java script view in couchbase
function (doc,meta) {
emit(meta.id,doc);
}
So, when I remove the statement query.setkey(this.Key) it works returns me all the tables, what am I missing here .. How can I change the function to refect only the table name mentioned in the key
Change the map function like this:
function (doc,meta) {
emit(doc.table,null);
}
it is good practice not to emit the entire document like:
emit(doc.table, doc)
NB: This is surprisingly important:
i have tried using setKey("key") so many times from Java projects and setting the key using CouchBase Console 3.0.1's Filter Result dialog, but nothing get returned.
One day, i used setInclusiveEnd and it worked. i checked the setInclusiveEnd checkbox in CouchBase Console 3.0.1's Filter Result dialog and i got json output.
query.setKey("whatEverKey");
query.setInclusiveEnd(true);
i hope this will be helpful to others having the same issue. if anyone finds another way out, please feel free to add a comment about it.
i don't know why their documentation does not specify this.
EXTRA
If your json is derived from an entity class in a Java Project, make sure to include an if statement to test the json field for the entity class name to enclose you emit statement. This will avoid the key being emitted as null:
if(doc._class == "path.to.Entity") {
emit(doc.table, null);
}

Categories

Resources