get values from client side to server side (node.js + express.js) - node.js

I'm still trying to understand the concepts of node.js so please don't blame me if this is a dumb question..
In node.js, is it possible to get a value from index.jade to index.js?
For example:
index.jade
a(href="/bla" name="someName") Blabla
index.js
router.get('/bla', function(req, res){
//get value of name ("someName") or string ("Blabla")
console.log(req.body.name) ??
});
If this is not possible, I would like to know why...
Thanks.

No, it's not possible, for the simple reason that the name attribute in your HTML doesn't get passed to the server (any server, not necessarily a Node-based server).
If you want to pass a value in a GET request, you generally pass it as part of the URL:
a(href="/bla?name=someName") Blabla
This will generate the following HTML:
Blabla
In your server code, you can access the value using req.query.name.
Taking this a step further: if you have a variable available to your template called "name", you can use something similar, but a bit more dynamic:
a(href="/bla?name=" + encodeURIComponent(name)) Blabla
encodeURIComponent makes sure that any "special" characters (that may have a special meaning in URL's) will be encoded properly.

Related

Why is Express converting & to &amp%3B and how do I handle it?

I am running Express on NodeJS and I receive a request that looks something like https://myserver.com/processCampaign?id=12345679&campaignId=123456.
Express converts that to id=12345679&amp%3BcampaignId=123456. So now I can't get the campaignId because I'm getting 'amp;campaignId':'123456' in the query string instead.
So I'm wondering, do I have something set wrong in Express or should I be handling this differently?
In express multiple queries are seperated with '&'. You don't need to use 'amp;' before the next query string. In your case, the url below will give you both the id and campaignId query.
https://myserver.com/processCampaign?id=12345679&campaignId=123456
If you log req.query now, you will get
{ id: '12345679', 'campaignId': '123456' }
Because I have no control over the inbound request (which is incorrect), I have no choice but to handle it on my side. I've read that the inbound URI is most likely incorrect because it is being double-encoded on their side.
Here's the solution I have come up with:
JSON.parse(JSON.stringify(req.query).replace('amp;campaignId', 'campaignId'))
If anyone has a better idea I'm open to other solutions.

Get params using ExpressJS

I'd like to get a specific param using ExpressJS with "#" instead of "?" in the url...
My URL :
http://localhost:3000/#access_token=LMkdfkdmsklmfdkslklmdskfmsda
I'd like to get "access_token" and "req.params.access_token" doesn't work...
Anthony
Short answer: you can't.
Longer answer: fragment identifiers (that's the part after the #) are supposed to be evaluated on the client and are not supposed to be sent to server. Your express app has no way of knowing them.
You could try to convert them to query parameters or path variables (i.e. by handling fragment identifier change in javascript) to make them visible server-side.

Get return value of `include` in jade template

What I basically try to accomplish is to re-use jade partials/templates when getting data through a socket connection. Non working example:
socket.on('company_created', function(company) {
var html = include _company;
$('#companies ul').append(html);
});
Normally I had to create a new li and set the content like so (which is working as expected):
$('#companies ul').append($('<li>').text(company.name));
This is okay for a simple list, but if I had complexer list and stuff, this could get messy pretty quick, plus I had to write plain HTML again, so I figured re-using my already existing jade templates with all their goodness would be awesome, but had not luck, yet.
Any clue?
PS: Please do not tell my to use Ember, Backbone, Derby, Meteor, Angular or whatsoever.
Thanks in advance!
You can compile your jade sources to JS with jade.compile. Then include these sources in the client-side javascript, include jade's runtime.min.js, and refer to your jade templates as to normal JS functions in your client-side code.
For example,
server.js
app.get('/templates/:template.js', function (req, res) {
var template = req.params.template;
response.end([
"window.templates = window.templates || {};",
"window.templates[\"" + template + "\"] = " + jade.compile(template + ".jade", { client: true; });
].join("\r\n"));
});
client.js
$(function() { $("#placeholder").html(window.templates["content"]({user: "Daniel" })); });
content.jade
h1: Hello #{user}!
index.jade
!!!
html
head
script(src='/lib/jquery/jquery.js')
script(src='/lib/jade/runtime.min.js')
script(src='/templates/content.js')
script(src='/scripts/client.js')
body
#placeholder
Note that the code above might be syntactically incorrect and is provided solely to illustrate the idea.
we have a build step that compiles them to functions sort of like penartur mentioned. I dont use extend or include (which dont work on the client anyway ATM), but personally I find we have absolutely no need for that on the client at all since the DOM provides all the separation we need.

Accessing jQuery object in JADE

During login, I save the userId in a jQuery cookie, so that I can access it by $.cookie('userId').
Now that I am trying to access it from Jade, as,
- if ($.cookie('userId') === userId)
I get an error
$ is not defined
How can I access the cookie ?
My code:
- if (($.cookie('userId')) === userId)
input(type='submit', value='Move')
else
input(type='submit', disabled, value='Move'')
You seem to misunderstand concepts. Let me give you a lecture. ;)
Basics. Cookie is stored on the client-side. So using jQuery $.cookie('userId') will retrieve it when this script is run on the client-side.
But here you use JADE templating engine on server-side. So you didn't even send the page to the client-side yet. So what cookie do you want to retrieve? There is no cookie, because you are at the server.
There's more. Running $.cookie('userId') throws the error, because you are on the server-side. There is no $ object. And there cannot be, because you cannot use jQuery on server-side (well, actually you can, but this is irrelevant at the moment). Did you define $ object in your route system? Or did you define helper $? I don't think so.
Express+JADE tutorial. Now let me give you a short tutorial. Say you have a view (in app.js)
app.get('/', function(req, res){
res.render('index.jade', { code: 500 });
});
Now in index.jade you can use code as a variable. So you can write your index.jade for example like this:
// some code
- if (code == 500)
input(type='submit', disabledm, value='Move')
- else
input(type='submit', value='Move')
// some code
and now it will work! You may also use JavaScript functions in template if you predefine them. For example (in your app.js)
app.helpers({
positive: function(no) { return no > 0; }
});
then in index.jade template you can use
- if (positive(-13))
input(type="submit")
and even combine these two concepts
- if (positive(code))
// do some stuff
To cookie or not to cookie. If you really need to use cookies (and you shouldn't except for sessions or CSRF for example) then you need to use client-side JavaScript. This means that you need to add (after jQuery)
script(src='my-path/my-script.js')
to the index.jade file and write my-script.js like this
$(document).ready(function() {
if ($.cookie('userId') == userId) {
// do something like append input to some holder
}
});
But there are several problems with that solution. First: what is userId (second part of equality)? You need to predefine it in your index.jade. For example using
script
var userId = #{ user.id };
and adding user object in your route. Second: cookies are local variables. Setting them requires additional server code which I do not thing you would like. This makes maintaining the app harder. And finally: storing a user's id in a cookie seems to be pointless. The final user don't even have to know it's own id. The server needs to know! Sessions system comes handy here.
Final note. The code you wrote shows us that you cannot distinguish between server-side and client-side JavaScript. The solution to your problem is to learn, learn and learn. Read tutorials and everything about JADE, Express and Node.js.
What #freakish said is right. You're trying server side vs. client side.
If the cookie is set you should be able to access it on server like so
app.use(express.cookieParser());
app.get('/', function(req, res){
// index is jade template
// local variable on jade template holds cookie value
// use req.cookies.userid
res.render('index', { userid: req.cookies.userid });
});

Jade template, how to pass concrete object to pages?

I have a jade template for my node.js project. I would like to send an object to the jade template and pass it to a function inside the page (to render something).
I am sure I send the right stuff from the server like this
res.render(__dirname + '/pages/viz.jade', {
vizJson: newJson,
});
in the client I do something like this:
script
sunburst(#{vizJson})
Thus, inside a script function, I want to call a function that creates my visualization with some json I created on the server side.
The problem is that when rendered I have something like sunburst([Object object]). I also tried to send the stringified version of the JSON but when I do JSON.parse(#{vizJson}) it complains like Unexpected token &.
The json I send is always different and has different level of depths.
Does anyone knows what to do?
Thanks
I hope this is going to help someone. I solved it like this:
script
sunburst(!{JSON.stringify(vizJson)})
Notice the ! and the {...} wrapping the stringify method.
For this to work, you need to stringify on the server.
res.render(__dirname + '/pages/viz.jade', {
vizJson: JSON.stringify(newJson),
});
Then, as you mentioned, parse the JSON on the client.
script
sunburst(JSON.parse(#{vizJson}))
Hope that helps!
Oddly enough, for me the solution involved no calls to JSON.parse. I stringified my object on the server and just used the !{vizJson} method and got my object clientside.
Per the docs, unescaped string interpolation: http://jade-lang.com/reference/interpolation/
On the JS side, you send back
res.render(__dirname + '/pages/viz.jade', {
vizJson: JSON.stringify(newJson),
});
On the HTML side, I have found that something like:
JSON.parse( '!{vizJson}' )
works.

Resources