Interpolating values in HTML attributes - Pug (Jade) - node.js

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

Related

Making Handlebars.js exclude rendering attributes where the source value is null?

I'm trying to create dynamic XMLs based on data stored in a javascript object. The problem is that the source data for certain attributes may contain null, which will result in Handlebars rendering the attribute with an empty string, while I would like Handlebars to just ignore it, and not render it at all.
I suppose I could make a template with a helper like this:
<item {{if id}}id={{id}}{{/if}}></item>
But it just seems like a lot of work, and makes the whole thing unreadable.
Is there a nicer way of getting the same results? Or would it perhaps be a better idea to traverse the whole XML after rendering and deleting attributes having empty strings?
I would recommend creating a very simple Handlebars helper. It could take a key and a value as parameters, but only return formatted attribute if value is 0 or truthy. For example:
Handlebars.registerHelper('attr', function (key, value) {
if (!Handlebars.Utils.isEmpty(value)) {
return new Handlebars.SafeString(key + '="' + Handlebars.escapeExpression(value) + '"');
}
});
Your template would invoke the helper in the following manner:
<item {{attr 'id' id}}></item>
Note: I have added the HTML escaping of value just in case it contains a quote character.
Also, if your are able to use ES6, a Template Literal would be prettier:
return new Handlebars.SafeString(`${key}="${Handlebars.escapeExpression(value)}"`);
I have created a fiddle for your reference.

Handlebars helper not working with global variable in Express

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.

Problems with variables inside styles using pug

I'm building a little app with NodeJS and Pug as engine.
I just want to insert a variable inside an element style, but can't find the way to make it work. Here is the code:
- var grados = 45;
span.glyphicon.glyphicon-arrow-up(style={transform:'rotate(#{grados}deg)'})
I think the problem is the parenthesis from the transform attribute, I tried it with another simpler approach like color:grados (- var grados = 'red') and it worked fine. Any ideas?
I'm afraid you've stumbled upon a common issue in Pug: Support for attribute interpolation has been dropped, so that syntax is no longer supported. See the page in the Pug docs relating to this. There is no 'clean' solution to fix this, other than simply building the attribute string with string concatenation:
- var grados = 45;
span.glyphicon.glyphicon-arrow-up(style={transform:'rotate(' + grados + 'deg)'})

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