If my list is empty, I want to output this:
<div id="some-id">
</div>
If my list is non-empty, I want to output this:
<div id="some-id">
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>etc</li>
</ul>
</div>
Note that I output the <ul>
and </ul>
tags at most once, and only if the list is non-empty.
The following code is close to how I would do this in PHP, but is obviously wrong:
<div id="some-id">
{{#items}}
<ul>
{{/items}}
{{#items}}
<li>{{name}}</li>
{{/items}}
{{#items}}
</ul>
{{/items}}
</div>
If items
is a 3 item list, I'm going to get 3 <ul>
's - obviously not what I want.
I realise I could set some other key as a boolean flag (hasItems
, perhaps), but this feels redundant.
Is there a more elegant way I can output a block only once for a non-empty list?
Mustache is a logic-less template syntax. It can be used for HTML, config files, source code - anything. It works by expanding tags in a template using values provided in a hash or object. We call it "logic-less" because there are no if statements, else clauses, or for loops.
A logic-less template is a template that contains holes for you to fill, and not how you fill them. The logic is placed elsewhere and mapped directly to the template. This separation of concerns is ideal because then the template can easily be built with different logic, or even with a different programming language.
var template = "Hello {{ name }}"; This is the Mustache template. The {{ name }} is a Mustache tag which is replaced with the data value. var text = Mustache.
The Mustache templates consist of tag names surrounded by { { } } (which resemble mustaches – hence the name) and are backed by a model object containing the data for the template.
If you don't want to or can't reformat your data or templating engine, you can also just check items.length
before rendering the <ul>
tags. Some people frown upon this, but it's definitely an alternative to Max's answer.
{{#items.length}}
<ul>
{{items}}
<li>{{name}}</li>
{{/items}}
</ul>
{{/items.length}}
You could use non-false values of a section. name
would have to be an object inside of items
data = { 'items' : { 'name' : ["Item 1", "Item 2", "etc"] } };
You template would look like:
<div id="some-id">
{{#items}}
<ul>
{{#name}}
<li>{{.}}</li>
{{/name}}
</ul>
{{/items}}
</div>
Here's an example on jsFiddle showing the rendering of an items
object with names and without -- http://jsfiddle.net/maxbeatty/fpQwk/
The other two answers do not work for the Ruby implementation of Mustache. My solution was to send an additional parameter as part of the template context; e.g.
template = <<EOF
{{#has_items}}
<ul>
{{#items}}
<li>{{.}}</li>
{{/items}}
</ul>
{{/has_items}}
EOF
items = ['one', 'two', 'three']
context = { items: items, has_items: items.any? }
Mustache.render(template, context)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With