Running through this useful walkthrough for Node.js authentication with Passport, but utilising Jade templating rather than ejs. When actually running the app, the correct values are displayed in the HTML, but it annoys me that command-line jade complains. Any ideas why?
Here is the calling code:
exports.myAccount = function (req, res) {
res.render('myAccount', {
title: 'Welcome back.',
user: req.user
})
};
... and a snippet of the Jade file (myAccount.jade) :
div.row
div.col-sm-6
div.well
h3
span(class="fa fa-user")
| Local
p
strong id
| : #{user._id}
br
strong Username
| : #{user.local.username}
Finally, the error when running Jade is:
TypeError: myAccount.jade:22
20| p
21| strong id
> 22| | : #{user._id}
23| br
24| strong Username
25| | : #{user.local.username}
Cannot read property '_id' of undefined
at eval (eval at <anonymous> (..../lib/jade.js:172:8), <anonymous>:138:49)
As already mentioned, the values do actually render, so how do I get Jade to quit complaining??
adv-THANKS-ance
The short answer: provide some data on the command line so jade can properly render your string interpolation expressions such as #{user._id}.
jade --obj '{"user": {"_id": "42", "local": {"username": "bob"}}}' myAccount.jade
Explanation: Jade takes 2 things as input: some jade syntax plus some data. In your app, the data is provided by your code taking req.user, etc, so jade has what it needs to render the template to HTML. On the command line, there's no data there, so you have to provide it as I've done above.
Bonus Tip: There's more concise ways to express your template without so many pipes:
div.row
div.col-sm-6
div.well
h3
span.fa.fa-user Local
p
strong= "id: #{user._id}"
br
strong= "Username: #{user.local.username}"
Related
Trying to switch out Mongo and put in Postgres (in other words, similar code worked fine with Mongo). Getting Cannot read property 'length' of undefined on the following code. I'm sure it's simple but I'm new to this whole stack so having trouble tying it together. Not a lot of examples on knex, so even though the docs are pretty good, I'm having trouble finding an example to copy.
I'm obviously pulling the right data but am stuck on how to get jade to display it.
Stack: Node/Express/Knex/Postgres/Jade
users.js
router.get('/', function(req, res, next) {
db.select().from('users').limit(1)
.then(function(users) {
console.dir(users)})
.then(function(users) {
res.render('users', {users: users})})
.catch(function(error) {
console.error(error)
})
});
users.jade
extends layout
block content
h1 Users
ul
for user in users
p
input(type="text", name="name", value="#{user.name}")
input(type="text", name="admin", value="#{user.admin}")
input(type="text", name="smsNumber", value="#{user.smsNumber}")
console
[ { uid: 1,
name: 'Don',
admin: 'true',
smsNumber: '4077023951',
created_at: null,
updated_at: null } ]
browser at localhost:3000/users
C:\Users\dvande03\Personal\dailychallenge\views\users.jade:6 4| h1 Users 5| ul > 6| for user in users 7| p 8| input(type="text", name="name", value="#{user.name}") 9| input(type="text", name="admin", value="#{user.admin}") Cannot read property 'length' of undefined
TypeError: C:\Users\dvande03\Personal\dailychallenge\views\users.jade:6
4| h1 Users
5| ul
> 6| for user in users
7| p
8| input(type="text", name="name", value="#{user.name}")
9| input(type="text", name="admin", value="#{user.admin}")
Cannot read property 'length' of undefined
at eval (eval at <anonymous> (C:\Users\dvande03\Personal\dailychallenge\node_modules\jade\lib\index.js:218:8), <anonymous>:51:31)
at eval (eval at <anonymous> (C:\Users\dvande03\Personal\dailychallenge\node_modules\jade\lib\index.js:218:8), <anonymous>:106:4)
at eval (eval at <anonymous> (C:\Users\dvande03\Personal\dailychallenge\node_modules\jade\lib\index.js:218:8), <anonymous>:119:22)
at res (C:\Users\dvande03\Personal\dailychallenge\node_modules\jade\lib\index.js:219:38)
at Object.exports.renderFile (C:\Users\dvande03\Personal\dailychallenge\node_modules\jade\lib\index.js:380:38)
at Object.exports.renderFile (C:\Users\dvande03\Personal\dailychallenge\node_modules\jade\lib\index.js:370:21)
at View.exports.__express [as engine] (C:\Users\dvande03\Personal\dailychallenge\node_modules\jade\lib\index.js:417:11)
at View.render (C:\Users\dvande03\Personal\dailychallenge\node_modules\express\lib\view.js:126:8)
at tryRender (C:\Users\dvande03\Personal\dailychallenge\node_modules\express\lib\application.js:639:10)
at EventEmitter.render (C:\Users\dvande03\Personal\dailychallenge\node_modules\express\lib\application.js:591:3)
at ServerResponse.render (C:\Users\dvande03\Personal\dailychallenge\node_modules\express\lib\response.js:961:7)
at C:\Users\dvande03\Personal\dailychallenge\routes\users.js:11:13
at tryCatcher (C:\Users\dvande03\Personal\dailychallenge\node_modules\bluebird\js\main\util.js:24:31)
at Promise._settlePromiseFromHandler (C:\Users\dvande03\Personal\dailychallenge\node_modules\bluebird\js\main\promise.js:454:31)
at Promise._settlePromiseAt (C:\Users\dvande03\Personal\dailychallenge\node_modules\bluebird\js\main\promise.js:530:18)
at Promise._settlePromises (C:\Users\dvande03\Personal\dailychallenge\node_modules\bluebird\js\main\promise.js:646:14)
res.render should look like this: res.render(view [, locals] [, callback]), where locals is an object whose properties define local variables for the view.
In your case that means changing the line where you render to:
res.render('users', {users: users})
You pass an object with local variables to render. In the jade-file you use the keys in the object when you want to refer to the values.
Solved it but I don't completely understand why. I commented out the console.dir before the render and it works. Is that because the users in the console.dir .then didn't pass to the render .then?
I accepted the answer above too because without that, I couldn't have gotten here. Thank you #tomtom.
In Jade, is it possible to create a conditional if statement in a dynamicscript section?
For example:
doctype html
html
head
script.
-if( locals.display_JS )
console.log("Display_JS is TRUE")
-else
console.log("Display_JS is FALSE")
(locals.display_JS is a parameter pass to Jade in res.render.)
If display_JS is true, the desired output should look like:
<script ...>console.log("Display_JS is TRUE")</script>
However the output is:
<script>
-if( locals.display_JS )
console.log("Display_JS is TRUE")
-else
console.log("Display_JS is FALSE")
</script>
It could be that I am thinking wrong. My objective is to render different javascript functions based on parameters sent to res.render.
It can be done the other way, use the . whenever you want to nest javascript code.
doctype html
html
head
script
if( locals.display_JS )
.
/** Some JS code **/
console.log("Display_JS is TRUE")
else
.
console.log("Display_JS is FALSE")
Jade will not mess with anything within a script block. If you really need to use jade logic inside a script block you can get a little tricky and do something like this:
Router Code:
router.get('/', function(req, res){
res.render('index', {run_this:true});
});
Jade Code:
div
| <script type='text/javascript'>
if(run_this)
| console.log("Ran this!");
else
| console.log("Didn't run this");
| </script>
Another approach to running logic based on jade variables within a script tag is to do something like this:
script.
if(!{run_this}){
console.log("Ran This!");
}
When you use script. everything that comes after will be interpreted as plain text by jade. If you need to mix markup and plain text you can use |. For example:
script
| function bar(){
if(true)
| console.log("Ran this")
else
| console.log("Don't run this")
| }
I'm currently working through some Node.js ExpressJS and MongoDB and have hit a snag with the Jade. I keep getting an input is self closing and should not have content error when I go to my newuser page. I've checked everything on this site, been through the jade-lang docs and have come up short, could really use some guidance with this Jade shenanigans. Thanks everyone!!
Here is my code:
extends layout
block content
h1= title
form#formAddUser(name="adduser",method="post",action="/adduser")
input#inputUserName(type="text", placeholder="username", name="username")
input#inputUserEmail(type="text", placeholder="useremail", name="useremail")
button#btnSubmit(type="submit", value="submit")
And here is my error message:
/home/evan/dev/nodetest1/views/newuser.jade:7 5| //- h1= title 6| form#formAddUser(name="adduser",method="post",action="/adduser") > 7| input#inputUserName(type="text", placeholder="username", name="username") 8| input#inputUserEmail(type="text", placeholder="useremail", name="useremail") 9| button#btnSubmit(type="submit", value="submit") 10| input is self closing and should not have content.
The error says exactly what the problem is, but unless you know how to translate it, that doesn't mean it's easy to understand :D
input#inputUserName(type="text", placeholder="username", name="username")
input#inputUserEmail(type="text", placeholder="useremail", name="useremail")
button#btnSubmit(type="submit", value="submit")
will try to put #inputUserEmail inside #inputUserName and #btnSubmit inside #inputUserEmail because of the indentation. It should just be
input#inputUserName(type="text", placeholder="username", name="username")
input#inputUserEmail(type="text", placeholder="useremail", name="useremail")
button#btnSubmit(type="submit", value="submit")
This is because in HTML, <input> elements do not have children, so the nesting is not allowed.
I am trying to run sparkleshare-dashboard which is an open source. Up till now i got many errors because i have no fimiliarity with the technology used in it. So, this time when i run app.js from command prompt using node command i got this error.
Warning: missing space before text for line 20 of jade file "D:\Imports\sparkles
hare-dashboard/views/createFirstUser.jade"
Error: D:\Imports\sparkleshare-dashboard/views/createFirstUser.jade:21
19| script(type="text/javascript")
20| $("#login").focus(function()
{
> 21| $("#loginlabel").fadeOut();
22| });
23| $("#login").blur(function() {
24| if ($("#login").val().length == 0) {
unexpected token "indent"
at Parser.parseExpr (D:\Imports\sparkleshare-dashboard\node_modules\jade\lib
\parser.js:229:15)
at Parser.block (D:\Imports\sparkleshare-dashboard\node_modules\jade\lib\par
ser.js:689:25)
at Parser.tag (D:\Imports\sparkleshare-dashboard\node_modules\jade\lib\parse
r.js:806:26)
at Parser.parseTag (D:\Imports\sparkleshare-dashboard\node_modules\jade\lib\
parser.js:719:17)
at Parser.parseExpr (D:\Imports\sparkleshare-dashboard\node_modules\jade\lib
\parser.js:188:21)
at Parser.block (D:\Imports\sparkleshare-dashboard\node_modules\jade\lib\par
ser.js:689:25)
at Parser.tag (D:\Imports\sparkleshare-dashboard\node_modules\jade\lib\parse
r.js:806:26)
at Parser.parseTag (D:\Imports\sparkleshare-dashboard\node_modules\jade\lib\
parser.js:719:17)
at Parser.parseExpr (D:\Imports\sparkleshare-dashboard\node_modules\jade\lib
\parser.js:188:21)
at Parser.parseExpr (D:\Imports\sparkleshare-dashboard\node_modules\jade\lib
\parser.js:227:21)
You have a syntax error in your code, you simply missed a dot and this causes another error, see my fixed example at the end:
script(type="text/javascript")
$("#login").focus(function(){
$("#loginlabel").fadeOut();
});
will prompt an Unexpected token "indent" error. Because Jade sees your $("#loginlabel").fadeOut(); as another line of code and this line has, for Jade, a wrong indentation.
Generally this "indent" errors are always pointing, in the end, to a wrong indentation.
So to get rid of this error, just add a dot at the end of the script tag and make clear thats a hole part oft none Jade code is following, like:
script(type="text/javascript").
$("#login").focus(function() {
$("#loginlabel").fadeOut();
});
This (see that dot) will give you the following HTML output:
<script type="text/javascript">
$("#login").focus(function() {
$("#loginlabel").fadeOut();
});
</script>
The correct syntax is:
script.
document.location = "https://google.com"
This is my configuration file.
docpadConfig = {
templateData:
site:
title: 'hello docpad'
getTitle: ->
#site.title
getString: ->
'just a string'
}
# Export the DocPad Configuration
module.exports = docpadConfig
From a jade layout when I do title= site.title it renders ok. When I try to call the helper function title= getTitle() the console outputs this:
error: An error occured:
ReferenceError: /Volumes/Data/project/am/lab/docpad/hello_docpad/src/layouts/default.html.jade:21
19|
20| //- Our site title and description
> 21| title= getTitle()
22|
23| //- Output DocPad produced meta elements
24| != getBlock('meta').toHTML()
site is not defined
at docpadConfig.templateData.getWat (/Volumes/Data/project/am/lab/docpad/hello_docpad/docpad.coffee:10:16)
at eval (eval at <anonymous> (/Volumes/Data/project/am/lab/docpad/hello_docpad/node_modules/docpad-plugin-jade/node_modules/jade/lib/jade.js:170:8), <anonymous>:47:64)
Looks like I can't access the site object from inside the helper function.
I'm sure I'm missing something trivial, maybe a plugin is needed for this... can't find out "wat" is wrong here.
I've found the solution looking into a similar issue in a docpad skeleton. This relates to a bug in the Jade pre-processor.
Update to "docpad-plugin-jade": "~2.4.1" fixes the issue.