node, express, jade: How to create select options from a hash - node.js

I've just started to play around with node, express and thus, jade. I try to do something like this in a jade template:
my-options = {"this": "something", "that": "something else", "those": "more stuff", "these": "also included"}
form
select(name="myselection")
each option, key in my-options
option(value="#{key}") option
However, all I get is an 500 server error which is not helpfull at all. What am I doing wrong here? Any help would be much appreciated.
Update
I've just figured out, that jade templates themselves cannot contain variable definitions. Thus, the my_options hash needs to be defined in the corresponding router.js file and passed as an parameter to the appropriate result.render() function.

Your first line must be executable JS code and 'my-options' is not a valid JS variable name.

Actually, you can define variables in Jade, you just have to start the line with a hyphen. A - at the start of a line tells Jade to execute the code that follows without outputting it. A = at the start of a line tells Jade to execute the code that follows and output it after it's done.
So for example if you do
- var foo = "bar"
= 2+2
p #{foo}
you will see this in your page source:
4
<p>bar</p>

Related

How can put Numeral.js library in pug file Node js?

I am using nodoe js and nodemailer. How can I use numeral.js to format numbers in pug file. Something like this.
#{numeral(number).format('0,0.00')}
If try this i getting numeral is not a function
You need to pass numeral function to your template otherwise (as you already stated) it will not be defined. Since you did not specify any code it is hard to tell how exactly you start the rendering of you pug file.
I usually handle it that way that I define a helper function which I then pass to the template:
const numeral = require('numeral');
function formatNumber(num) {
return numeral(number).format('0,0.00');
}
Usage in the template works like this:
#{formatNumber(number)}

get values from client side to server side (node.js + express.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.

Scope of exported variable in express and jade

I'm having a few issues with Jade and scope of variables exported from the route. This might be an obvious answer, but my googling abilities have failed me.
In my route, I have this code :
res.render('index', {title: "App",
csvData: json // This is a json object
};
In my view, I want to display the length of the json object on the click of a button. My jade looks like this :
extends layout
block content
script
-var test123 = csvData;
-console.log(test123.length);
div
button.btnCSV(onclick='console.log(test123)') Save As CSV
The first console.log prints the correct length, but when I do press the button, it tells me that test123 is undefined. I think this has something to do with the difference between client side/server side variables. If that is the case, is there anyway to make a server side variable accessible to a client side scope?
I'm not sure how your example would work with the script content prefixed with a -, this indicates unbuffered code. JavaScript that runs server side and that produces no direct output, so your in-line script is most likely empty.
Similarly your onclick handler is just compiling a string on the server, which is the main problem you appear to report.
In order to achieve what you trying to do, you should define a function in the script block which can be called from your buttons onclick handler. Take care to ensure that your script keyword ends with a . so that the following lines are treated as block content of the script.
Here's what your template should look like.
extends layout
block content
script.
var test123 = !{JSON.stringify(csvData)};
function printLength() {
console.log(test123.length);
}
div
button.btnCSV(onclick='printLength()') Save As CSV
Then on the server side make sure you're returning an actual JavaScript object, or an Array, and not a string representation... it should look like this
res.render('index', {title: "App",
csvData: [{ val1: 'value1', val2: 'value2' }]
};
This allows variables to be used for server side scripting (if required) as well as client side.

How do I fix the Implicit textOnly message that appears when starting an Express server?

When starting Express server with node app.js I see the following message displayed:
Implicit textOnly for script and style is deprecated. Use script. or style. instead.
What does this message mean and how can I fix it?
This issue and this pull request discuss the message in detail. Basically you will soon have to tell Jade explicitly that a script is text only. The current method of:
script
var a = 2;
is deprecated. It will be replaced with:
script.
var a = 2;
So to fix this message you need to explicitly show that the block is text by adding a dot after script or style
As stated here this is being removed to make Jade easier to learn and to permit the use of Jade code blocks in the block.
As I mentioned above, this applies to implicit style as well.

Passing raw Markdown text to Jade

I'm playing around with my first Node.js Express application, and as every programmer knows, the first thing you should build when testing out a new framework is a blog! Anyway, I'd like to write the articles in Markdown and then render it in the view. I saw that Jade allows for this to be done inside the view itself, using filters, but I can't get that working.
To simplify the situation, here's an example of what I'm talking about.
//app.js
res.render("article", {
md : "Hello World!\n\n*Woo*"
});
//article.jade
section
:markdown
#{md}
But, that outputs this: <section><h1>{md}</h1></section>... it isn't substituting in the variables I've passed to it.
Then I tried this:
//article.jade
section
:markdown
!{md}
And the output is this:
<section><p>Hello World!
*Woo*</p></section>
So, now it's not parsing the markdown!
I have been able to get this to work by parsing the markdown in the app.js file and then passing the HTML to the view to display, but I don't know, that seems a bit messier.
Is there a way to pass variables into Jade filters?
You can do this with a function passed in to jade from node:
var md = require("node-markdown").Markdown;
Then pass it into the view as a local:
res.render('view', { md:md, markdownContent:data });
Then render it in the jade view by calling the function:
!= md(markdownContent)
The node module node-markdown is deprecated. The marked is advanced new version. You can try like this
var md = require('marked');
Inside your router
res.render('template', { md: md });
Inside your jade template
div!= md(note.string)
I don't think jade can do this out of the box. One way to accomplish it that might feel slightly cleaner than pre-rendering the markdown is to create a helper function called markdown that takes a markdown string and returns HTML. Then you could do something like
section
!= markdown(md)
The markdown function should be included in the locals data when you render the jade template and can directly use a markdown library to convert the markdown syntax to HTML.
If you are using Scalate's Jade support you can enter:
section
:&markdown
#{md}
You can also import external files with:
section
:&markdown
#{include("MyFile.md")}

Resources