Handlebars helper not working with global variable in Express - node.js

I have an app running on Node, Express and express-handlebars. The variable is a result of a query assigned to res.locals and condition helper "ifCond" like this one. The code that needs to be rendered is a in a partial. The problem is that helper is not working when using a variable with it:
//getting the variable works
{{groups}} // Group2
//works with standart block helper
{{#if groups}}1{{else}}2{{/if}} // 1
//helper is working
{{#ifCond 5 "==" 5}}equal{{else}}not equal{{/ifCond}} //equal
//not working when using variable with helper
{{#ifCond groups "==" Group2}}equal{{else}}not equal{{/ifCond}} //not equal
What can cause it not to work with a helper? Thank you.

You need to put Group2 in quotes so it is treated as a string by the template parser:
{{#ifCond groups "==" "Group2"}}
since you're trying to pass a string to your helper. When you don't put quotes around it, the handlebars parser tries to resolve it as a variable name just like with groups right before it.

Related

Set temporary variable and reuse it further down in pug template

I am trying to pass along some values from my nodejs/express backend into the template (using res.render({...})), store it in some variables, then pass it further up until the front end (The usecase is that I need to do some mild calculation on the passed values and stored them in some intermediate variables)
I know I can do this in the pug file
block append script
script.
const foo = parseInt(#{stat.get('fooStat')}, 10);
But then later it seems that I can not refer to this later in my pug template, say here
span #{foo}
The value is empty, I guess because it is undefined... What's the usual way to accomplish that.
Adding the period after the script tag signals to pug that its contents should be treated as plain text. This is handy when you want to write javascript for client-side consumption, but any variables declared are inaccessible to pug.
script.
const foo = 10;
span #{foo} // foo is undefined here
If you want to define a variable that pug can use later in the template, do so using unbuffered code.
- const foo = 10
span #{foo} // renders <span>10</span>

Interpolating values in HTML attributes - Pug (Jade)

I am trying to construct an anchor tag with a dynamic href attribute in Jade.
I did go through the docs and some SO questions but they didn't help me. This is what I tried.
a(href= "http://www.imdb.com/title/#{movie.imdb_id}") Know more
But it renders
http://www.imdb.com/title/#{movie.imdb_id}
rather than
http://www.imdb.com/title/tt1234567
However this works
a(href= "http://www.imdb.com/title/" + movie.imdb_id) Know more
and this too.
- var url = "http://www.imdb.com/title/" + movie.imdb_id;
a(href= url) Know more
What's wrong with the first version?
Interpolation is only available in text.
You need to use JS string concatenation for attributes:
a(href="http://www.imdb.com/title/" + movie.imdb_id) Know more
If you JavaScript runtime supports ES2015 template string, you can also use them (notice the backticks):
a(href=`http://www.imdb.com/title/${movie.imdb_id}`) Know more
Reference
the pug variable declaration doesnt work in this case using #{...}
the right syntax goes this way,
a(attributes) Know more
a(href="http://www.imdb.com/title/"+ movie.imdb_id) Know more
the attributes is an expression so it renders correcly, or you could use ES5 template literals with back quotes to render the variable along side the text which becomes
a(href=`http://www.imdb.com/title/${movie.imdb_id}`) Know more
note that when using back quotes with template literals your variable expression are enclosed in parenthesis and a leading $ sign, that is ${..expression..}
When you quote it simply tells pug "this is a string". That's basic JS. Interpolation works with #{'#{interpolation}'} too! is an example which renders "Interpolation works with #{interpolation} too!"
I don't have any knowledge about pug(jade)
But my guess is "a(your code)" is already a signal to pug(jade) that it is in the controller's scope already.. and "{variable}" is also an indicator that you are accessing controller's scope. so
a(href= "http://www.imdb.com/title/#{movie.imdb_id}") Know more
for "{}" inside a() is no longer an indicator that your are trying to access controller's scope because you're already in the controller's scope.. so "{}" inside a() is just a string, {movie.imdb_id} is part of the link string.
So in order for the framework to identity that movie.imdb_id is a variable, you should separate it from the actual string.
NOTE: This is just a guess..I'm using angular

Optional Partials in DustJS

Is it possible to have optional partials in Dust? Let's say I define a layout like this:
<div>
{>"{module}"/>
</div>
I have been defining the module in Express's res.locals object. However, what if I forgot to define a module, or I actually want a default module for use when I do not define one? Worse, what if I did define one but it's the incorrect module, meaning there's no template file in the view folder with the name of that module? I don't want the user to see the ugly error message, which seems to be something like:
Error: ENOENT, open 'view_path\{module}.dust'
where {module} is the name of the module, or an empty string if I did not specify a res.locals.module. Should I resort to try-catch blocks (not even sure how to do them in dust), or is there a method for making templates optional, rather than required? NOTE: The template would be optional, but the module variable would (usually) still be a string. It seems that dust sections are optional, meaning if the exact key is not available, the section is simply not included. For example, say I have the context {friends: [{name: "Harry"}, {name: "Ron"}, {name: "Hermione"}]}. If I define the section:
{#friends}
{name} is {age} years old.
{/friends}
it will output
Harry is years old.
Ron is years old.
Hermione is years old.
Notice there are 2 spaces between is and years in each case, where the age would be if we defined any ages. If this functionality is included, how is it that neither the original creators of dust nor LinkedIn thought to not require partials? How do I specify optional partials in dust?
You could use a conditional like so,
<div>
{?module}
{>"{module}"/>
{:else}
{>"{YourDefaultPartial}"}
{/module}
</div>
This will work when {module} is either undefined or an empty string or a falsey value.
But, in case its a string pointing to a partial that does not exist, it'll throw an error. Hope this helps.

Equality operator in Jade

I am trying to write a mixin in Jade. I would like to pass a parameter through mixin to build same type of block with different value at different states. In the mixin I want to write a conditional that checks if passed parameter is equal to some value. But unfortunately it is not working and I can't find proper documentation anywhere. My code section is following:
mixin test(id)
if territoryList
each val in territoryList
- if (val.parentArea==id){
button.btn.btn-primary.btn-block=val.name
- }
And I am calling it like test('1')
What is the problem?
I don't think your if is supposed to be a javascript if.
Don't you want this ?
mixin test(id)
if territoryList
each val in territoryList
if val.parentArea==id
button.btn.btn-primary.btn-block= val.name

Passing variable from jade to ng-init not working

I'm trying to pass an object from jade to ng-init in angular
This: doesn't work:
ng-init='tables=!{JSON.stringify(tables)}'
This: expands but,
ng-init='tables=#{JSON.stringify(tables)}'
the output is unescaped and filled with "s
ng-init="tables={"12":{"id":....
and the view isn't updated in either of the cases. This article implies that first one should work, but like I said, it doesn't even expand,
ng-init='tables=!{JSON.stringify(tables)}'
in source code shows up exactly the same in the HTML source
ng-init='tables=!{JSON.stringify(tables)}'
Actually, the #{...} approach seems to work fine.
It is probably the way console.log prints attributes' values that confused you.
ng-init="tables=#{JSON.stringify(tables)}"
Take a look at this short demo.
In what use-case you want to pass data directly from Jade to angular? I think you could to this job in controller like this :
$scope.init = function () {
// init stuff
}
...and in your view :
ng-init = init()

Resources