18

I am new to nodejs and trying to create a jade file for the html content myfile.jade: Here are the contents of the file:

extends layout
block content
   script
     function capitalize(s) { 
       console.log("Testing js exec");
       return s.charAt(0).toUpperCase() + s.slice(1); 
     };
  table
    - each item in list
      tr
        td
          a(href="/collection/#{item.name}") #{capitalize(itemName)}

However, when running it throws the following error:

Error: mweb/views/collections.jade:8
    6|   script
    7|     function capitalize(s) { 
  > 8|       console.log("Testing js exec");
    9|       return s.charAt(0).toUpperCase() + s.slice(1); 
    10|     };

unexpected text ;

If I remove console.log, it throws the error saying:

TypeError: mweb/views/collections.jade:18
  > 18|             a(href="/collection/#{item.name}") #{capitalize(itemName)}

As far as I realized, capitalize is being called during the jade compilation and the function is not available as the script tag is also compiled into the html. What is the best way for me to have this call evaluated on a) server side or b) client side?

Thx

Kiran
  • 5,478
  • 13
  • 56
  • 84

3 Answers3

23

You need to define function in the scope of jade, not in JS you generate:

block content
   -  function capitalize(s) { return s.charAt(0).toUpperCase() + s.slice(1); };
  table
    - var list = ['one', 'two']
    - var itemName = 'test test'
    - each item in list
      tr
        td
          a(href="/collection") #{capitalize(itemName)}

but it's probably better to have it outside of template and pass reference to helpers object

Andrey Sidorov
  • 24,905
  • 4
  • 62
  • 75
  • 1
    thanks. that works. Do you mind giving any references on how to use the helpers? – Kiran Jan 06 '14 at 02:40
  • There is no special helpers library. I'm referring to user-supplied functions as 'helpers'. When you render template, you pass your objects as input, and together with data you can pass reference to your helper / utility functions – Andrey Sidorov Mar 06 '14 at 22:49
  • [Is](http://stackoverflow.com/questions/23962845/evaluate-custom-javascript-method-circularjson-with-jade) there a way to require it? like `- var CircularJSON = require('circular-json')`? ( – laggingreflex May 30 '14 at 20:43
  • require it outside of template. Or you can actually pass reference to "require" to your template context and use it from inside jade code. There is no magic in `require`, it's just a normal javascript function – Andrey Sidorov May 31 '14 at 03:22
  • @AndreySidorov I know it may sound stupid. But how will we handle an async/wait case like if the function called capitalize would take some time to respond? I mean capitalize function would have called some API with params that is available in the jade template. In this case it seems like template gets rendered before we get data. – Bijay Kushawaha May 19 '20 at 04:41
  • 1
    @BijayKushawaha no, you need to prepare all the data for your template fully in advance before you start rendering, I'm not aware of any "concurrent" rendering mode in jade/pug. – Andrey Sidorov May 20 '20 at 05:05
  • @AndreySidorov Thank you for your response. I did the same thing and it worked. – Bijay Kushawaha May 20 '20 at 12:41
9

I realize this is really old, but when you declare a function in jade, you need to do

script.

not

script

the period makes the difference and will allow jade to pick up that it's in fact a piece of code, rather than HTML.

user1241388
  • 147
  • 1
  • 3
  • 12
6

By this #{capitalize(itemName)} you are trying to call function that is passed to the template from the controller (back-end).

For instance (/routes/index.js):

res.render('index', { title: 'Express test', fs : { echo : lang} });

While in index.jade

 a(href='/register') #{fs.echo('xxx')}

where

lang

is a function defined earlier that takes some parameter.

gregiolo
  • 115
  • 1
  • 5