Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mustache Conditions and Loops

Here are the resources:

JSON

{
  "badges":{
    "unlocked": [
      {"name": "Win 1"},
      {"name": "Win 2"},
      {"name": "Win 3"}
    ],
    "locked":[
      {"name": "Lose 1"},
      {"name": "Lose 2"},
      {"name": "Lose 3"}
    ]
  }
}

Algorithm

{{ if_has_badges }}
<div class="badges">
  <h1>Badges</h1>

  {{ if_has_badges_unlocked }}
    <div class="badges-unlocked">
      <h2>Unlocked!</h2>
      {{ loop_badges_unlocked }}
      <a href="#" class="badge">
        <strong>{{ name }}</strong>
      </a>
      {{ end_loop_badges_unlocked }}
    </div>
  {{ end_if_has_badges_unlocked }}

  {{ if_has_badges_locked }}
    <div class="badges-locked">
      <h2>Locked!</h2>
      {{ loop_badges_locked }}
      <a href="#" class="badge">
        <strong>{{ name }}</strong>
      </a>
      {{ end_loop_badges_locked }}
    </div>
  {{ end_if_has_badges_locked }}

</div>
{{ end_if_has_badges }}

How I can write this algorithm to work with Mustache compiler?

I need to do this to work with two sides, first is the RubyOnRails application and the second is the client-side (JavaScript).

like image 221
Caio Tarifa Avatar asked Feb 23 '13 15:02

Caio Tarifa


2 Answers

There are two solutions to your problem.

Using selections and inverted selections

Here is an example from the mustache documentation:

{
  "repos": []
}

Template:

{{#repos}}<b>{{name}}</b>{{/repos}}
{{^repos}}No repos :({{/repos}}

Output:

No repos :(

As you see the inverted selections let me do conditional logic. In your case it would look something like:

Json:

var viewModel = {
    badges:[]//badges here
}
viewModel.anyBadges = badges.length >0;

Mustache:

    <div class="badges-unlocked">
   {{#anyBadges}}
      <h2>Unlocked!</h2>
   {{/anyBadges}}
   {{#badges_unlocked}}
      <a href="#" class="badge">
        <strong>{{ name }}</strong>
      </a>
   {{/badges_unlocked}}

Don't do logic in logic-less templating

This is what I would do. If you have conditional logic in your Mustache templates I think you're doing it wrong. You can either use Handlebars instead which is much more advanced in this regard or move your logic someplace else (to your javascript).

Please see the Mustache readme

like image 66
Benjamin Gruenbaum Avatar answered Sep 25 '22 01:09

Benjamin Gruenbaum


The best answer (for both Ruby and JavaScript) is to encapsulate your logic (the if_has_badges type questions) into a View class.

You can actually fake it for the little bit of logic you need in both Ruby and JavaScript by using the array length property:

{{# badges.length }}
<div class="badges">
  <h1>Badges</h1>

  {{# badges.unlocked.length }}
    <div class="badges-unlocked">
      <h2>Unlocked!</h2>
      {{# badges.unlocked }}
      <a href="#" class="badge">
        <strong>{{ name }}</strong>
      </a>
      {{/ badges.unlocked }}
    </div>
  {{/ badges.unlocked.length }}

  {{# badges.locked.length }}
    <div class="badges-locked">
      <h2>Locked!</h2>
      {{# badges.locked }}
      <a href="#" class="badge">
        <strong>{{ name }}</strong>
      </a>
      {{/ badges.locked }}
    </div>
  {{# badges.locked.length }}

</div>
{{/ badges.length }}

But that's a bit of a dirty way of doing it...

like image 28
bobthecow Avatar answered Sep 27 '22 01:09

bobthecow