boolean logic within a handlebars template

27,871

Solution 1

You can't do it directly but it isn't that hard to do with a little bit of arguments parsing and a variadic helper. Something like this:

Handlebars.registerHelper('if_all', function() {
    var args = [].slice.apply(arguments);
    var opts = args.pop();

    var fn = opts.fn;
    for(var i = 0; i < args.length; ++i) {
        if(args[i])
            continue;
        fn = opts.inverse;
        break;
    }
    return fn(this);
});

And then in a template you can say:

{{#if_all a b c}}
    yes
{{else}}
    no
{{/if_all}}

You can use as many arguments to {{#if_all}} as you need. You might want to adjust the truthiness test to match Handlebars since {{#if}} treats

`false`, `undefined`, `null`, `""` or `[]` (a "falsy" value)

as falsey and everything else as truthy whereas [] is truthy in JavaScript.

Demo: http://jsfiddle.net/ambiguous/vrb2h/

Solution 2

may be you can try this handlebars helper:

Handlebars.registerHelper('ifCond', function (v1, operator, v2, options) {

switch (operator) {
    case '==':
        return (v1 == v2) ? options.fn(this) : options.inverse(this);
    case '===':
        return (v1 === v2) ? options.fn(this) : options.inverse(this);
    case '<':
        return (v1 < v2) ? options.fn(this) : options.inverse(this);
    case '<=':
        return (v1 <= v2) ? options.fn(this) : options.inverse(this);
    case '>':
        return (v1 > v2) ? options.fn(this) : options.inverse(this);
    case '>=':
        return (v1 >= v2) ? options.fn(this) : options.inverse(this);
    case '&&':
        return (v1 && v2) ? options.fn(this) : options.inverse(this);
    case '||':
        return (v1 || v2) ? options.fn(this) : options.inverse(this);
    default:
        return options.inverse(this);
}

});

and invoke it like this :

 {{#ifCond showDistance "&&" distance}}
      <span class="distance">
          {{distance}}
      </span>
 {{else}}
      {{#if showRegion}}
           <span class="region">
           </span>
      {{/if}}
 {{/ifCond}}
Share:
27,871
BostonJohn
Author by

BostonJohn

Software developer in San Diego. A lot of C and python experience, working in Java now.

Updated on July 05, 2022

Comments

  • BostonJohn
    BostonJohn almost 2 years

    Is it possible to perform boolean logic within a handlebars conditional?

    Right now I spoof this behavior with a controller function, so I end up with the controller

    App.ApplicationController = Ember.Controller.extend({
        bool1: true,
        bool2: true,
        both: function(){ return this.bool1 && this.bool2; }.property('content.both'),
    });
    

    Which allows me to use a handlebars template of

    <script type="text/x-handlebars">
      {{#if both}}
         <p> both were true </p>
      {{/if}}
    </script>
    

    and that works fine, but raises some problems. First off, it obscures what's happening (particularly if good function names aren't used). Secondly, it seems to infringes a bit on the MVC separation.

    Is it possible to do something along the lines of

    <script type="text/x-handlebars">
      {{#if bool1 && bool2}}  <!-- this will not actually work -->
         <p> both were true </p>
      {{/if}}
    </script>
    

    and have it work?