Sunday, April 27, 2014

Conditional Attributes with Jade

I've been working with Node lately to create a complete web application (not just a Websockets back-end to an HTML5 game) and I am using the Jade template engine with Express.

I really like Express and Jade but the other day I ran into an issue and I just couldn't figure out how to get the HTML output I wanted. The problem was that I wanted to output attributes conditionally. Not just the values of the attributes conditionally, but the whole attribute. Sometimes I wanted to output this:

<img something="whatnot" foo="bar" src="/images/frog.svg" />

and sometimes I wanted to output this

<img something="whatnot" src="/images/frog.svg" />

based on a condition.

It's easy to output attribute values based on conditions. The value for an attribute can actually be any JavaScript expression. So these are all valid in Jade templates:

img(foo='bar')

img(foo=(x == 12 ? 'bar' : 'ribbit'))

img(foo='var-in-the-' + b + '-middle')

I just couldn't figure out how to prevent an attribute from being output at all based on a condition. I finally settled on this:

img(foo=(x == 12 ? 'bar' : ''))

which output this HTML when x is anything but 12:

<img foo="" />

Not really ideal, but I could make it work. I did make it work, but it bothered me. I lost sleep over it. I couldn't eat. I was withdrawn from my family. My children thought that I didn't love them anymore. Okay, maybe I'm exaggerating a little. But seriously, I didn't like it. I didn't want that attribute to come out at all. Today, I found the answer:

img(foo=(x == 12 ? 'bar' : undefined))

Undefined! Of course! Like I said, any valid JavaScript expression can be used. Now when x is anything but 12, the foo attribute is undefined and does not output to the HTML. In case you are curious, null also works in place of undefined. Using undefined is probably better though.

I am sleeping much better now.