Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mustache templates: How to output a block only once for non-empty lists

Tags:

mustache

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?

like image 402
G Mawr Avatar asked Apr 11 '12 09:04

G Mawr


People also ask

How mustache template works?

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.

Which is logic-less templates?

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.

How to include mustache in JavaScript?

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.

What is in mustache template?

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.


3 Answers

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}}
like image 101
broox Avatar answered Oct 18 '22 13:10

broox


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/

like image 37
maxbeatty Avatar answered Oct 18 '22 13:10

maxbeatty


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)
like image 1
endemic Avatar answered Oct 18 '22 11:10

endemic