How do I accomplish an if/else in mustache.js?

JavascriptTemplatesMustache

Javascript Problem Overview


It seems rather odd that I can't figure how to do this in mustache. Is it supported?

This is my sad attempt at trying:

    {{#author}}
      {{#avatar}}
        <img src="{{avatar}}"/>
      {{/avatar}}
      {{#!avatar}}
        <img src="/images/default_avatar.png" height="75" width="75" />
      {{/avatar}}
    {{/author}}

This obviously isn't right, but the documentation doesn't mention anything like this. The word "else" isn't even mentioned :(

Also, why is mustache designed this way? Is this sort of thing considered bad? Is it trying to force me to set the default value in the model itself? What about the cases where that isn't possible?

Javascript Solutions


Solution 1 - Javascript

This is how you do if/else in Mustache (perfectly supported):

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

Or in your case:

{{#author}}
  {{#avatar}}
    <img src="{{avatar}}"/>
  {{/avatar}}
  {{^avatar}}
    <img src="/images/default_avatar.png" height="75" width="75" />
  {{/avatar}}
{{/author}}

Look for inverted sections in the docs: https://github.com/janl/mustache.js#inverted-sections

Solution 2 - Javascript

This is something you solve in the "controller", which is the point of logicless templating.

// some function that retreived data through ajax
function( view ){

   if ( !view.avatar ) {
      // DEFAULTS can be a global settings object you define elsewhere
      // so that you don't have to maintain these values all over the place
      // in your code.
      view.avatar = DEFAULTS.AVATAR;
   }

   // do template stuff here

}

This is actually a LOT better then maintaining image url's or other media that might or might not change in your templates, but takes some getting used to. The point is to unlearn template tunnel vision, an avatar img url is bound to be used in other templates, are you going to maintain that url on X templates or a single DEFAULTS settings object? ;)

Another option is to do the following:

// augment view
view.hasAvatar = !!view.avatar;
view.noAvatar = !view.avatar;

And in the template:

{{#hasAvatar}}
    SHOW AVATAR
{{/hasAvatar}}
{{#noAvatar}}
    SHOW DEFAULT
{{/noAvatar}}

But that's going against the whole meaning of logicless templating. If that's what you want to do, you want logical templating and you should not use Mustache, though do give it yourself a fair chance of learning this concept ;)

Solution 3 - Javascript

Your else statement should look like this (note the ^):

{{^avatar}}
 ...
{{/avatar}}

In mustache this is called 'Inverted sections'.

Solution 4 - Javascript

Note, you can use {{.}} to render the current context item.

{{#avatar}}{{.}}{{/avatar}}

{{^avatar}}missing{{/avatar}}

Solution 5 - Javascript

You can define a helper in the view. However, the conditional logic is somewhat limited. Moxy-Stencil (https://github.com/dcmox/moxyscript-stencil) seems to address this with "parameterized" helpers, eg:

{{isActive param}}

and in the view:

view.isActive = function (path: string){ return path === this.path ? "class='active'" : '' }

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionegervariView Question on Stackoverflow
Solution 1 - JavascriptEneko AlonsoView Answer on Stackoverflow
Solution 2 - JavascriptBGerrissenView Answer on Stackoverflow
Solution 3 - JavascriptanonymView Answer on Stackoverflow
Solution 4 - JavascriptHafthorView Answer on Stackoverflow
Solution 5 - JavascriptDanielView Answer on Stackoverflow