79

Is it possible in Handlebars to check if a string is equal to another value without registering a helper? I can't seem to find anything relevant to this in the Handlebars reference.

For example:

{{#if sampleString == "This is a string"}}
...do something
{{/if}}
Machavity
  • 30,841
  • 27
  • 92
  • 100
colmulhall
  • 1,548
  • 3
  • 18
  • 33

15 Answers15

130

It seems you can't do it "directly"

Try use helper, why not?

Register helper in your javascript code:

Handlebars.registerHelper('ifEquals', function(arg1, arg2, options) {
    return (arg1 == arg2) ? options.fn(this) : options.inverse(this);
});

Use in template:

{{#ifEquals sampleString "This is a string"}}
    Your HTML here
{{/ifEquals}}

More details here: Logical operator in a handlebars.js {{#if}} conditional

Update: Another way:

lets assume, your data is:

var data = {
    sampleString: 'This is a string'
};

Then (using jQuery):

$.extend(data, {isSampleString: function() {
    return this.sampleString ==  'This is a string';}
});

An use template:

{{#if isSampleString}}
    Your HTML here
{{/if}}
nwxdev
  • 4,194
  • 3
  • 16
  • 22
Mihail
  • 1,543
  • 1
  • 10
  • 6
  • i am also trying to achieve the same but in my case, it's throwing an error **Missing helper: "ifEquals** – Wasif May 21 '19 at 05:22
  • @Wasif did you figure out this? – user557657 Jul 20 '20 at 19:44
  • @user557657 I put all custom helpers in a single JavaScript file that is loaded with the page. You can call `Handlebars.registerHelper` anywhere in your code but I find it easier to keep track of the helpers I've written if they're in one place. – Paul Aug 27 '20 at 14:38
26

The previous answer with match does not work for me, I get an error on the if statement (something like 'must have only one argument').

However, I just found the solution here without having to write any more helper:

{{#if (eq person "John")}} hello {{/if}}
Community
  • 1
  • 1
Kerhael
  • 461
  • 5
  • 15
  • 10
    But I believe that for "eq" to work you need to have the Ember Truth Helper addon, as stated [here](https://stackoverflow.com/a/29101000/1548894). In my case, I don't have that addon. – zed Jan 16 '18 at 14:32
  • for those attempting... this solution did not work for me in Shiny Server template files. e.g., https://stackoverflow.com/q/32207842/2371031 – Brian D Sep 23 '20 at 16:01
  • 2
    which results in `message: "Missing helper: "eq"`. So, you do first need to register this helper. – bvdb May 05 '21 at 16:22
  • The helper class is there for the export method. – prasanth pr Jan 25 '23 at 08:27
21

I would just use helpers like this:

Handlebars.registerHelper('ifeq', function (a, b, options) {
    if (a == b) { return options.fn(this); }
    return options.inverse(this);
});

Handlebars.registerHelper('ifnoteq', function (a, b, options) {
    if (a != b) { return options.fn(this); }
    return options.inverse(this);
});

Then in your code:

{{#ifeq variable "string"}} 
    ... do this ... 
{{/ifeq}}
{{#ifnoteq variable "string"}} 
    ... do this ... 
{{/ifnoteq}}
Richie Thomas
  • 3,073
  • 4
  • 32
  • 55
Pablo Varando
  • 221
  • 2
  • 3
9

Use handlebars-helpers, which provides eq helper

Vic Seedoubleyew
  • 9,888
  • 6
  • 55
  • 76
6

For a single line solution that does not require dependencies you can use:

Handlebars.registerHelper('eq', (a, b) => a == b)

Then use it as other examples have noted as a nested call:

{{#if (eq sampleString "This is a string"}}
...do something
{{/if}}
dwightbcoder
  • 61
  • 1
  • 1
5

Just came to this post from a google search on how to check if a string equals another string.

I use HandlebarsJS in NodeJS server-side, but I also use the same template files on the front-end using the browser version of HandlebarsJS to parse it. This meant that if I wanted a custom helper, I'd have to define it in 2 separate places, or assign a function to the object in question - too much effort!!

What people forget is that certain objects have inherit functions that can be used in the moustache template. In the case of a string:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/match

An Array containing the entire match result and any parentheses-captured matched results; null if there were no matches.

We can use this method to return either an array of matches, or null if no matches were found. This is perfect, because looking at the HandlebarsJS documentation http://handlebarsjs.com/builtin_helpers.html

You can use the if helper to conditionally render a block. If its argument returns false, undefined, null, "", 0, or [], Handlebars will not render the block.

So...

{{#if your_string.match "what_youre_looking_for"}} 
String found :)
{{else}}
No match found :(
{{/if}}

UPDATE:

After testing on all browsers, this doesn't work on Firefox. HandlebarsJS passes other arguments to a function call, meaning that when String.prototype.match is called, the second argument (i.e. the Regexp flags for the match function call as per above documentation) appears to be being passed. Firefox sees this as a deprecated use of String.prototype.match, and so breaks.

A workaround is to declare a new functional prototype for the String JS object, and use that instead:

if(typeof String.includes !== 'function') {
    String.prototype.includes = function(str) {
        if(!(str instanceof RegExp))
            str = new RegExp((str+'').escapeRegExp(),'g');
        return str.test(this);
    }
}

Ensure this JS code is included before you run your Handlebars.compile() function, then in your template...

{{#your_string}}
    {{#if (includes "what_youre_looking_for")}} 
        String found :)
    {{else}}
        No match found :(
    {{/if}}
{{/your_string}}
tshepang
  • 12,111
  • 21
  • 91
  • 136
Jon
  • 99
  • 1
  • 4
3

In Handlebars, the parenthesis are used to invoke the first item listed as a function, using (optional) subsequent items as parameters. So, the syntax from Ember CAN be used without Ember, provided you can set the context yourself. For example:

    context.eq = function(param1, param2) {
        return param1 === param2;
    }

    context.notEq = function(param1, param2) {
        return param1 !== param2;
    }

Once you do that, you can use the standard {{#if}} and {{#unless}} block operations:

{{#if (eq someVar "someValue") }}

Be careful of switching contexts with {{with}} or when using inline partials. You can lose track of your defined "eq" function. The guaranteed way to work, regardless of new contexts:

{{#if (@root.eq someVar "someValue") }}
1

You cannot directly compare the strings in handlebars and you have to use a helper. I tried the above solutions with my Koa app and couldn't register the helper. The below code worked for me and i think this should work for express apps as well. I hope this helps someone.

Code in server.js

var handlebars = require('koa-handlebars');

const isEqualHelperHandlerbar = function(a, b, opts) {
            if (a == b) {
                return opts.fn(this) 
            } else { 
                return opts.inverse(this) 
            } 
        }
        
app.use(handlebars({
    viewsDir: './app/views',
    layoutsDir: './app/views/layouts',
    defaultLayout: 'main',
    helpers : {
        if_equal : isEqualHelperHandlerbar
    }
}));

Code in HBS file where fruit is the variable to be compared:

 <select id={{fruit}}>
   <option >Choose...</option>
   <option value="apple" {{#if_equal fruit "apple"}} selected {{/if_equal}}>Apple</option>
   <option value="mango" {{#if_equal fruit "mango"}} selected {{/if_equal}} >Mango</option>
 </select>
Ojus sangoi
  • 636
  • 7
  • 7
1

There are a lot of answers but I will show what works for me if someone has the same error as me (basically sends me a error that options.fn and options.reverse aren't functions) so I decided to go for a simple solution using the sub-expression helpers and it works (unespected because I try all the before solutions, getting the same error)

In short words I just make a simple comparison between the two arguments and returning the value that you want, like this (Using Helpers)

in your server.js || app.js


Handlebars.registerHelper('functionName', function (value, value2) {
    if(value == value2) {
        return this;
    }
  });

In this case I don't give a else conditional but if you want you can do it, and here's how the hbs file should go

{{#if (functionName value value2)}}

In my case in value I put a value of my Database (MongoDB) and in value2 I use to compare a String, so I think you can compare whatever kind of value, also if you are iterating on a each be sure you put the if conditional inside them

Last but not less important be sure you have the const Handlebars = require('handlebars'); on your code or will send you a error, hopefully will help someone

you can read about the sub-expressions here

Steven León
  • 145
  • 2
  • 6
0

A common case for a simple, re-usable helper function is to cause a return of string1 if values are equal and string2 if they are not.

Example:

Helper (let's call it "ifEqual" and send 4 parameters):

helpers: {

    ifEqual: function (obj, value, trueString, falseString) {
            return ( (obj===value) ? trueString : falseString );
}

Template Use:

For this example, assume the template receives a "transaction" object with a "transactionType" property: { transactionType: "expense", description: "Copies" }

Let's say our template has a <select> for the Transaction Type, with various <option>s as shown. We want to use Handlebars to pre-select the option which coincides with the value of transactionType.

Our new {{ ifEqual }} helper is used to insert "selected" for the <option> with the matching value of "expense."

<select required id="selTransactionType" name="selTransactionType" class="form-control" onchange='transactionTypeChanged()'>
   <option value='hourly' {{ ifEqual transaction.transactionType "hourly" "selected" "" }} >Hourly fee</option>
   <option value='flat' {{ ifEqual transaction.transactionType "flat" "selected" "" }} >Flat fee</option>
   <option value='expense' {{ ifEqual transaction.transactionType "expense" "selected" "" }} >Expense</option>
   <option value='payment' {{ ifEqual transaction.transactionType "payment" "selected" "" }} >Payment</option>
   <option value='credit' {{ ifEqual transaction.transactionType "credit" "selected" "" }} >Credit</option>
   <option value='debit' {{ ifEqual transaction.transactionType "debit" "selected" "" }} >Debit</option>
</select>
Jeff Matthews
  • 602
  • 2
  • 7
  • 17
0

Node.js add this in server.js

const isEqual = function(a, b, opts) {
  if (a == b) {
    return opts.fn(this) 
  } else { 
    return opts.inverse(this) 
  } 
}

var hbs = require('hbs');
hbs.registerHelper('if_eq', isEqual);
wscourge
  • 10,657
  • 14
  • 59
  • 80
0

I had same difficulty as OP and decided to just sublet the call to Javascript rather than trying to bend Handlebars to my will ...

Javascript function (in global scope) -

function jsIfElse(compare1, compare2, trueResponse, falseResponse) {
  document.write((compare1 == compare2) ? trueResponse : falseResponse);
}

Handlebars snippet -

<select multiple id="batter_player_team">
  {{#each teamNamesForFilter}}
  <option value="{{this.id}}">                     <script>jsIfElse('{{this.is_active}}','Y','{{this.name}} *', '{{this.name}}');</script>
  </option>
   {{/each}} 
</select>
-1

Handlebars has a conditional operator called 'equal' that takes two parameters:

1.The variable

2.what your checking if the variable contains.

For examples, to check if 'status' contains 'Full Time':

{{#equal status "Full Time"}}  //status is the variable and Full Time is the value your checking for.
    code to be executed
{{else}}
    code to be executed
{{/equal}}
Mekanic
  • 137
  • 2
  • 10
-2

The Mandrill mail service supports Handlebars and here it is possible to use "backticks" to evaluate an logical expression in a #if block:

{{#if `operating_system == "OS X"`}}
  <p>Click here for instructions to install on a Mac</p>
{{elseif `operating_system == "Windows"`}}
  <p>Click here for instructions to install on a PC</p>
{{/if}}

I don't know if this possible in general, but you should try it out. It works fine for me.

pberggreen
  • 928
  • 6
  • 13
-2

Try:

{{#is item.status "complete"}} ... {{/is}}

user2662680
  • 677
  • 8
  • 16