Handlebars.js: if-block needs value to compare

Created on 15 Mar 2012  ·  82Comments  ·  Source: handlebars-lang/handlebars.js

I want to be able to write a resultcount like this:

{{#if count == 0}}No results{{/if}}
{{#if count == 1}}1 result{{/if}}
{{#if count > 1}}{{count}} results{{/if}}

This doesn't seems possible. Can this be made?

Most helpful comment

I was afraid of that.
I know something like that can be done with helpers... But, I mean, comparing stuff is so utterly basic, it should be in the default package.

All 82 comments

This can be done by helpers.
Look on this: http://kan.so/packages/details/handlebars-helpers
There is ifequal helper which enables comparing two values.
Similar solution can be used for your requirement.

I was afraid of that.
I know something like that can be done with helpers... But, I mean, comparing stuff is so utterly basic, it should be in the default package.

If it were to be included in the package it would be a helper anyway.

@andriijas quite right, it would indeed be a helper ;) Or not, since an if-block is so elementary.
Thanks for the link. It's helpful, but I'm itching to write a "helper" that overwrites the original if, to make it a _proper_ if. I'm sure it's possible. Any self-respecting template engine needs proper conditional formatting. Handlebars should be no exception.

You need to get over the fact that everything in handlebars that applys business logic to templates is helpers.

All the built in each, if etc are defined via registerHelper. Check:
https://github.com/wycats/handlebars.js/blob/master/lib/handlebars/base.js

So there is nothing "bad" with using helpers. Handlebars is more or less just a mustache template compiler and to get that extra business logic they use helpers. if think you just have a bad experience of the use of word "helpers" perhaps from rails or something.

I never said there's anything wrong with "helpers". It's just that a proper if-statement is not supposed to be an extension in my view. A helper (again, in my view) is something specific to a CMS or something. A helper is something that performs a special operation or condition. Something that isn't for everyone. That is, if it's defined outside the core library. A bit like jQuery-plugins perhaps: the most elementary things are built-in, the things that get you started. But things that aren't for everyone are defined outside the core library (i.e. in plugins). In jQuery-terms, a simple filter-function would not be a plugin.

An if-statement (in my view) does not apply to this plugin-paradigm. It's elementary, it's one of the most basic principles of programming and template engines...

A quick followup then. Here's what I've got so far:

Handlebars.registerHelper("when", function(lvalue, operation, rvalue, options) {
  console.log(arguments);
});

Using this in my template like {{#when riskfactor eq 0}}...{{/when}} I get in my console an array of [6, undefined, 0, function()]. The last one I get. That's what I need to call to process the content of this when-block. The first three... well, not so much. The "6" is actually the value of "riskfactor". Okay, I can go with that. The undefined is beyond me. I think Handlebars is trying to evaluate it on the input object, but that won't work. I want to get things that are actually _in_ the template, because values like these have nothing to do with my object.

I was expecting something like ["riskfactor", "eq", "0", function()]. Only then my function can go ahead and process that. How am I going to do that with "undefined"?

I think the philosophy of Handlebars (and other "logic-less" templates) is that the context that arrives for the template should be fully processed already. If your application's internal data structures don't perfectly align with what would be appropriate for a template (which will be the case almost every time), then you should insert a step before rendering the template that builds the template context from your application's internal data structures.

I believe that's the intention when people talk about "separating logic from presentation." Think of Handlebars as the view component of an MVC system. Your model already exists; all you must write now is the controller (in this case, it is a set of one-way bindings from model to view).

To answer your most recent question, you want to use this:

 {{#when "riskfactor" "eq" 0}}...{{/when}}

Handlebars expressions are either variable names or strings. If it's a variable name, you will get the value of the variable when looked up in the current context, not the name.

This is outside of the realm of Handlebars as some have pointed out.

No.
ANY template system can do a simple comparative if-else-block, and Handlebars can't. That makes Handlebars either rediculously incomplete, its makers incompetent (which is unlikely tho), or a system with a clouded perspective of the tasks of a templating system.

DONT use a LOGICLESS TEMPLATE ENGINE THEN. KTHXBAI!

Got it. Toodles.

@thany, @andriijas was probably a bit harsh, but he's right. Handlebars is intended to be logic-less. You can definitely make a bike with a motor, but many companies are happy making only motor-less bikes. Likewise, you can make a template system with more logic, but that's not something Handlebars is trying to do. Sorry it's not what you were looking for.

I have to side with @thany on the if helper. We should be able to pass any predicate into it. Not being able to really limits it's utility. I understand the philosophy behind logic-less templates but a dogmatic implementation is not really pragmatic (and thus the existence of the helpers, right?). I would say this is more like the bike company adding a variable gear ratio, which would be totally reasonable.

BTW, if you want to rage against the machine and do this, you can create a helper that takes the predicate as a string and then eval it (and make this twice heretical :smiling_imp:):

Handlebars.registerHelper('when', function (predicate, options) {
    var declarations = '';
    for (var field in this) declarations += field + ' = this.' + field + ',';
    if (eval(declarations + predicate)) { return options.fn(this); }
});

{{#when 'admin || superUser'}}
    crazy go nuts
{{/when}}

@thany look on it from best practice perspective, your Back-end should serve the data with all the logic already figured out Front-end (template) should just render it ... if you got good JSON representation of your backend objects than 95% cases can be satisfied with build in conditionals http://handlebarsjs.com/#conditionals

Seriously, not ALL (or even 95%) decisions made are backend-oriented. For example, to determine which classname to render, it is totally reasonable to make that decision in the template. Something like that is 100% tied to the frontend/template. The backend couldn't care less which classname is rendered. Or what about singular/plural words? That's another thing that can't be done with the if-block.

The backend in my opinion is responsible for providing data, and data ONLY, when working with rich templates like this. If the backend needs to give the template-parser ready-made variables for each and every situation that the template could possibly make a decision about (considering some flexibility here) they would be rediculously complicated just from the sheer amount of variables, let alone the backend that makes them.

You may as well put HTML in the backend if every decision that a template needs, needs another modification in the backend. That just takes away a big chunk of the purpose of templates. Decisions tied to the backend are on a completely different level. An if-block is not necessarily logic. It's just deciding what/how to render.

I can't believe this problem requires such a long discussion, is a proper if-block truly too much to ask for? :(

I am not going to argue for nor against implementing a basic comparison helper, but this is the very real case where I don't think I could've rendered the template without using a helper or changing the data structure:

    <select name="datatype">
      <option{{#ifeq type 'foo'}} selected="selected"{{/ifeq}}>foo</option>
      <option{{#ifeq type 'bar'}} selected="selected"{{/ifeq}}>bar</option>
      <option{{#ifeq type 'vaz'}} selected="selected"{{/ifeq}}>baz</option>
    </select>

But then again, the helper I wrote was three lines of code:

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

i agree with @thany, I also don't believe that this is something that should be outside of the template/view.

why exactly can't a template have logic in it? and how is handlebars providing a separation of logic and presentation? it still has an if statement doesn't it? are you saying that an if statement that simply tests for existence and/or "falseness" is in no way any different to an if statement that checks for (in)equality or any other condition?

the only — real — difference then is that unlike other template libraries, handlebars has a very poor/incomplete implementation of said logic under the guise of being "logic-less". i'm sorry, but that's completely nonsensical. if you want to remove logic you should remove the if statement altogether. you won't do that though, because ultimately a template needs logic for the same reason(s) why handlebars still has an if statement.

so, the statement "separating logic from presentation." is fallacious, not just for the reasons above, also because you're not removing "logic" from the template, you're simply moving it to another part of the template — i.e. the helper — and maybe you'll get code reuse — which would be a good thing — and maybe you don't, in which case you may get any number of helpers performing almost/exactly the same thing as other helpers, due to minor difference that would have been better by providing a correct implementation of if. how is this a good design decision?

i'm still struggling to understand why, if certain "logic" is inherently bound to a specific view and is of no importance, significance and/or use to anything other than the view itself, what the problem is exactly. it simply sounds like mvc extremism/overkill to me.

@andriijas if I could use a different template library I would, unfortunately the decision is out of my hands. as such any and all recommendations to use a template library that allows "logic" will unfortunately fall on deaf ears.

Have anyone actually looked at how the current if is implemented? (there is also unless which is nice)

Now that you have looked how the if is currently implemented, it might make more sense to you guys why handlebars have a simple and elegant default which satisfies most people.

Look here how easy it is to extend

https://github.com/elving/swag

https://github.com/elving/swag/blob/master/src/swag.comparisons.coffee

Accept that all your open sources projects dont provide everything you need to cook your bacon, just the foundations.

@andriijas yes, unless is just an if with the result inverted. i don't see how this compensates for anything. thanks for the helpers repo link, I've already written a helper, again though, i don't see how this compensates for anything.

Handlebars is a little over 10kb (minzipped) and swag is a little under 3kb (minzipped). So you add a 10kb template library to your codebase and you need another 3kb just to be able to add logic to your templates. logic which you and several others are saying you shouldn't have in your templates anyways?

this doesn't answer any of my questions and in fact it only serves to prove the point that it's nonsensical to disallow conditional tests other than existence/falseness in your if statement block.

@andriijas I'm looking at /lib/handlebars/base.js#L97, but i'm not really sure what you mean. It looks like there is some form of alternative usage of it, but the documentation does not specify this. Would you care to explain?

@constantology some people might need another 3kb, you and the other guys in this thread for example. The rest of the 3500 who starred this repo on github are not likely to complain, because they have solved their logic needs by either adding helpers or doing it before rendering the templates.

@piksel what you are looking at is the fact that the built in if is just an helper as any "addon" which many seem to have a problem with, thinking that helpers are slower or something.

There is nothing wrong with using helpers in your project. In one project I use some of the swag helpers, copied to my own view_helper file so its even less than 3k.

In one backbone project I have a getTemplateData method on my views, where I boil down complex logic to easier stuff that makes the templates cleaner and easier to follow, ah and also, its easier to unit test plain javascript than handlebars templates.

@andriijas that still doesn't answer any of my questions...

at this point i would be just reiterating what i have already said, so if you feel like you can actually provide a reasonable answer to any or all of the questions i have already asked, then I would be very happy to hear what you have to say. :)

p.s. the number of people that starred the repo and/or are using the library isn't necessarily an indication of how good a library is. there are more windows users than mac/linux combined and — depending on which browser stats site you look at — there are still more people using internet explorer 6, 7 and 8 combined than a more modern browser. that doesn't make windows a better operating system than osx or linux and it doesn't make older versions of internet explorer better than, modern standards, compliant browsers.

This whole discussion is asinine to me. An if helper is there, IT IS LOGIC. So the whole logic-less argument is a total straw man. It's like if a car had windows that would only roll down and people complained and wanted them to also roll up. And the manufacture said they were not going to change it because these cars followed a strict philosophy of not having mechanically controlled windows... Either you support it or you don't. A half-ass implementation should not be justified with a straw man argument.

I totally agree with and understand not having business logic in templates. But unless you're doing extremely trivial templates your going to have some view logic there. Handlebars obviously recognizes this since the if helper exists. Working around a hamstringed if helper by adding a bunch of view logic in your code is not the answer as @thany pointed out. I've done it before, it gets ugly fast.

@mikeobrien yes, I've already mentioned that in a previous comment. it was one of many questions that have gone unanswered.

I totally agree with and understand not having business logic in templates. But unless you're doing extremely trivial templates your going to have some view logic there.

nicely put. :^)

@constantology doh, sorry, guess I should have read the past comments better. :/

I agree with @constantology

FWIW I find Handlebars to be a really elegant and well written template library.

I understand the concept of blocks and helpers just fine, however, I don't think that creating a helper to do something small — that could be handled more elegantly by supporting it in core library — means a clear separation of logic and presentation. CSS is adding support for conditional statements and some of this can be achieved already with media queries, so logic in a purely presentational language is not necessarily a big boo-boo, if it is simply "view logic" as @mikeobrien put it.

I feel that this one limitation — lack of conditional checks in if/unless blocks — makes it a really hard to create elegant and encapsulated templates.

Also, I also agree with having a method to preprocess data before parsing it through a template, however, only for simple changes, not for re-formatting the entire data structure to bend it to any library's will. Why?

  1. this could potentially affect the overall performance of parsing if you need to take a complex data structure and create something more flat.
  2. based on 1, it can, potentially, make your view code more brittle — and harder to refactor — if changes are made to the original schema.
  3. it could also make two-way data-binding more tricky as you are no longer mapping the original data structure to the view, thereby increasing the amount of code may you need to track changes.

Those are just off the top of my head, I've not done any quantifiable research to back any of that up, but it's food for thought. :^)

for the original question, a if helper with comparison would be the wrong thing. it's a common scenario and helpers like:
{{#ifzero count}}No results{{/ifzero}}
{{#ifsingular count}}1 result{{/ifsingular}}
{{#ifplural count}}{{count}} results{{/ifplural}}
would be more helpful and would translate to what he really wants to do. the current if syntax is useful for (not) displaying empty values. a very common scenario too. if someone really needs an if with comparison it's very likely that it's business logic and he should not do it in the template.

That would do it indeed.
However, I still think it is not up to an engine to force developers into a certain corner, whether that is _in principle_ a good corner, or not. I think it should be up to the developer which is business logic, and which is template logic.

That is, unless the limitation of not being able to do comparisons is purely a technical limitation that somehow made it into a paradigm. That only means such a functionality could never be added should the need arise. I hope that's not what's happened.

Testing thany. Testing. You don't want to put comparisons in templates because you can't test this logic easily. It's much simpler to create simple boolean values via a data formatter for your template, and test it, than it is to hook into something like selenium and test it there.

This isn't just theory, this not is just 'in principle'. It would probably be real world technical debt bullshit to put even comparisons in templates, and to not test this logic. Don't write or use these helpers. I haven't used a helper yet for handlebars. However if you did use a helper, you could spy on it and test to make sure the thing ran, so it's better than comparisons being built into the templates.

There are a lot of logic free template systems that don't offer comparisons. For example in strongly typed languages like go, what does equality even mean? There are no comparisons in Go templates. There are mustache and handlebar implementations across languages and they are the same.

Removing logic like comparisons from templates doesn't make your life harder, it makes it easier. Technical debt is no joke, it can ruin products and even companies.

Come on.
Comaprisons are not that hard. It's not rocket science (or brain surgery).

In very simple micro-templates you don't need logic, but if it gets any more complicated, you're gonna need logic in templates. There is such a thing as "business logic" as well as "template logic". Determining what to do when there's only one item of something, or two, or ten. Paging, for example. Dividers. Simple "under 50%" & "over 50%" texts, and I could go on.

The fact that other template engines don't have logic in them, either, doesn't mean you should blindly follow them. They have it wrong, too, in my opinion.

Fact is, at some point, you going to have some kind of logic that you just don't need or want in the business logic, simply because it isn't business logic. I cannot convery to my fellow developers having to a boolean value in, for every concievable kind of comparison that any current or future template could ever need.

"it can ruin products and even companies"? Seriously?
Improper functionality can, too.

Whats wrong with it shipping what most people need and you adding a helper
for what you need? Everybody wins. Its not that hard, not like rocket
science.

If it is rocket science: https://github.com/elving/swag

On Saturday, May 18, 2013, thany wrote:

Come on.
Comaprisons are not that hard. It's not rocket science (or brain surgery).

In very simple micro-templates you don't need logic, but if it gets any
more complicated, you're gonna need logic in templates. There is such a
thing as "business logic" as well as "template logic". Determining what to
do when there's only one item of something, or two, or ten. Paging, for
example. Dividers. Simple "under 50%" & "over 50%" texts, and I could go on.

The fact that other template engines don't have logic in them, either,
doesn't mean you should blindly follow them. They have it wrong, too, in my
opinion.

Fact is, at some point, you going to have some kind of logic that you just
don't need or want in the business logic, simply because it isn't business
logic. I cannot convery to my fellow developers having to a boolean value
in, for every concievable kind of comparison that any current or future
template could ever need.

"it can ruin products and even companies"? Seriously?
Improper functionality can, too.


Reply to this email directly or view it on GitHubhttps://github.com/wycats/handlebars.js/issues/206#issuecomment-18104713
.

Most people _not_ using it may be due to the problem that is described here: no logic. So of course most people who actively use will be more-or-less content with it.

@thany I feel you and I agree with you.

I think the people behind handlebars don't want to give up on this one, but hey, what I'm going to tell you is amazing news:
You can _fork_ the project, add the patch and use your own fork.
Due to the magic of git, it should be fairly easy to keep up with new versions by just git pulling.

And wait for it, it gets better.

If this happens to be a big need and it's overall better, maybe people will start using your fork or even even better better, the guys behind handlebars will merge your fork back to origin/master :dancer:

have a good one ;D

If I would grant myself the time, sure!

I absolutly agree with @constantology. Its insane have template without logic. And if you wanted have logic-less template why you put there the: "if" statement what represent logic as red color danger... Does not makes sence. I think the basic comparision logic is needed as salt in soup. @mikeobrien :"A half-ass implementation should not be justified with a straw man argument." :+1:

There's something to be said for logicless templates. Though, I feel the problem is everyone here is confusing business logic with view logic. Business logic has no place in templates. Period. View logic, however, is another matter entirely. I think Handlebars realizes this which is why they added the if/else in the first place, they just got a little confused along the way.

I need to know whether my data array has one item or several, and based on that I want to join them with commas, or add a plural to a word. With the current if block, I cannot do this.

This is why I made this pull request: https://github.com/wycats/handlebars.js/pull/566 and accompanying jsfiddle: http://jsfiddle.net/YsteK/

This pull request supplies a new helper: ifTest, which takes a javascript expression that evaluates just like javascript would given the context. Enjoy.

Honestly this is such basic functionality it makes me feel that if you want to stick to this mindset of not having logic built into the framework (which seems completely illogical to me!) you need to reconsider the use of logical terms such as "if".

I find myself adding this to a lot of my projects simply because its so helpful when comparing things such as "0" and "1" to boolean other values:

Handlebars.registerHelper('ifCond', function(v1, v2, options) {
if(v1 === v2) {
return options.fn(this);
}
return options.inverse(this);
});

I think its totally fair to make the existing "if" functionality work the way it does, but do the English language a favor and pick another word (or make it do what people expect it to). It feels like a real perversion of the term "if" when it simply doesn't behave like a true if statement in any other context.

I'd like to add another vote for either removing if entirely, or allowing if to accept some basic comparison arguments, e.g. eq, ne, gt, etc. You'd end up with {{#if arg1 eq arg2}}. Of course, removing if entirely would make more sense for your "no logic in templates" philosophy (right now it's more like "no logic in templates _most of the time_ but _sometimes_ it's okay").

Without a helper, I end up doing stuff like this all the time:

<select>
    <option value='ak' {{#if ak_selected}}selected{{/if}}>AK</option>
    <option value='al' {{#if al_selected}}selected{{/if}}>AL</option>
    <option value='ar' {{#if ar_selected}}selected{{/if}}>AR</option>
    <option value='az' {{#if az_selected}}selected{{/if}}>AZ</option>
    <option value='ca' {{#if ca_selected}}selected{{/if}}>CA</option>
    ....
</select>

Which seems kinda silly to add all those extra properties to an object.

webgovernor - Check out this: http://jsfiddle.net/YsteK/

It's a helper that enables this functionality. It takes a javascript expression that evaluates just like javascript would given the context. Enjoy.

Thanks tniswong, that's very similar to my helper. I have the issue solved, I just wanted to highlight the hypocrisy of the Handlebars "logic-less" dogma.

No problem. I'm right there with you. I love handlebars, but its pretty useless without this helper.

I submitted this helper as a pull-request but it was rejected. So I submitted another pull-request that removed the if block. Also rejected. /sigh

Hahaha. Github needs an upvote button.

It was rejected? -_-

The obstinacy of Handlebars' logicless religion is truly mind-boggling.

566 and #568

He mentioned he might add it to the README, but I'm not holding my breath.

+1 to this! Argghhh!

FWIW, the Swag repo provides helpers that add comparison, sorting and other nifty stuff. I don't build anything in Handlebars without it.

That said, I personally agree with letting Handlebars stay as logic-less as possible since it keeps it clean, extensible and maintainable. If you want more, contribute to a repo like _Swag_ for things outside the scope of the project. Should the maintainers of this project change their mind, all it takes is a pull request :+1:

@aboutaaron If you're going to make a statement like, "letting Handlebars stay as logic-less as possible since it keeps it clean, extensible and maintainable", you should at least have the decency to:

  1. provide proof that handlebars contains no logic. If you have read the thread then you will see it has already been proven that handlebars contains incomplete logic in the form of an if statement that only checks for "truthyness", if you have not read through the thread then I would suggest you do so.
  2. provide proof that handlebars providing incomplete logic in the form of an if statement that only checks for "truthyness", in some way, "keeps it clean, extensible and maintainable".
    Isn't this a contradiction? If handlebars is extensible, doesn't that mean it would be trivial to provide a complete implementation of conditional statements?
    How would, for example, handlebars providing a complete if statement make it less clean, extensible and maintainable than a developer using handlebars AND swag?
    One could argue that using the swag helpers will make a codebase less clean, extensible and maintainable since you need to use a different helper for each comparison operator, i.e. gt, gte, is, isnt, lt, lte as well as for each logical operator, i.e. and, or.
    How does this make code more readable than doing all this the same as one would — inside an if statement — in any other language? If this were the case then I would assume programming languages themselves would do away with conditional statements that check for anything other than "truthyness"? I don't see this happening.

If by chance you're going to use the tired — and disproven — argument of "putting business logic in the template", please don't. this has already been addressed — several times, by several people —in this thread. At the same time, if that is something you consider a valid argument, then that would eliminate the need for using the swag library, contradicting your previous statement.

In conclusion, the fact that there are several libraries out there that seek to add completeness to the incomplete implementation of if in handlebars — in one way or another — shows that there is a need for this type of functionality in its core. Look at the JavaScript language itself, Harmony is introducing a lot of features which have been provided by third party libraries, iterators, modules, generators, classes, proxies, etc; and the and the DOM API has also implemented featueres which were provided by third party libraries, querySelector[All], CORS and there is even an implemention of DOM Promises in chrome canary.

There is no proof that "letting Handlebars stay as logic-less as possible since it keeps it clean, extensible and maintainable". At the same time, others and I have shown — in previous comments of this thread — that a little can go a long way, if handlebars were to provide a complete if implementation it would give developers a unified API to make their templates easier to read and maintain.

@constantology +1 Amen.

I just arrived here after trying {{#if something > something_else}} and realizing the truth of this situation. However, I'm tempted to agree with the handlebars people on this one. I used liquid for a long time, and comment threads like this inevitably lead to the addition of half-baked features like math and string concatenation that really did belong in the back end.

The goal with the "logic-less" if statement seems to be: do the logic part on the back end, and present handlebars with the "answer" as a single variable. If the answer is "yes" do this, otherwise do the other thing. I don't see a problem with that (having read the above comments), and am going to go fix my code now.

Working on some Ember applications and wanted to throw in my opinion. I feel that the #if statement would be better if it _(optionally)_ accepted an argument. I totally understand the desire to leave things logic-less, but it can be pretty frustrating to work with sometimes.

Imagine a simple list of questions that be selected or deselected. Really, what's the difference between these two blocks of logic?

{{#if isSelected question}}
  <p>This question is selected</p>
{{else}}
  <p>This question is NOT selected</p>
{{/if}}
{{#if question.isSelected}}
  <p>This question is selected</p>
{{else}}
  <p>This question is NOT selected</p>
{{/if}}

There are fairly big differences in how I need to write the code backing these two examples. It would be really nice to have the flexibility to choice either. I also don't really see how the first contains more logic than the second.

I felt the very same thing that this thread says. Then, I found this thread.
Therefore, I guess that I've just understood the philosophy of Handlebars.
Then, I figured out what I needed is a helper collection like Swag.

Now I have no problem because Swag will help me.
However, I got confused because the default if helper was too simple.
If you say Hanlebars is logic-less, I doubt Handlebars needs built-in helpers.
If it had no built-in helpers, I think that I could understand Handlebars' philosophy more easily.

I may not have a good understanding about logic-less and business logic, I want to tell you what I thought.

I believe that you simply can't consider a single if/unless (without conditionals) as logic, as it is just -in the logic-less context- a means to represent a boolean data, as the "{{foo}}" syntax is a means to represent a string data.

So I think the following behaviour should be stopped: "If it's logic-less, why is there an if statement? HA-HA, checkmate!!!"

Then change it to "{{#exists}}" instead of "{{#if}}" because that makes more sense.

On Oct 5, 2013, at 10:52 AM, cal127 [email protected] wrote:

I believe that you simply can't consider a single if/unless (without conditionals) as logic, as it is just -in the logic-less context- a means to represent a boolean data, as the "{{foo}}" syntax is a means to represent a string data.

So I think the following behaviour should be stopped: "If it's logic-less, why is there an if statement? HA-HA, checkmate!!!"


Reply to this email directly or view it on GitHub.

:thumbsup: for changing {{#if}} to {{#exists}} or {{#isTrue}}

I agree that we can find a more sensible name. 'exists' would do it, and my suggestions would be 'true' or 'on'.

But nonetheless, the name 'if' would still be more appropriate because of historical reasons. Handlebars' if implementation is syntactically no different than any other if implementation, it complies with the old "if ([predicate]) [do sth]" syntax.

What is different is that the [predicate] must be a bare bool variable, it can't be an expression. But this is not the limitation of 'if'. This is a more generic limitation caused by lack of support for expressions of the Handlebars interpreter. (Which is exactly what makes Handlebars logic-less btw, I think)

Which means this 'if' is no different than any other 'if'.

And trying to change the name of 'if' may be considered heresy by some, don't say I didn't warn you.

Call it {{#truthy}} and {{#falsey}} because that is all that {{#if}} and {{#unless}} do.

To the developers: get your heads out of the sand. Seriously. You can see that there's demand for a proper if-statement (and I intent to use the word 'demand' quite literally) so go and implement it, instead of whining about logiclessness. If you want you templates to be logicless, do away with ALL logic, including {{#if}} and {{#each}}.

JUST implement a proper if-statement.
Folks who strongly believe in their logiclessness, shall opt not to use it. Simple. As. That.

I even already did the work for you.

https://github.com/wycats/handlebars.js/pull/566
https://gist.github.com/tniswong/5910264

On Oct 5, 2013, at 3:20 PM, thany [email protected] wrote:

Call it {{#truthy}} and {{#falsey}} because that is all that {{#if}} and {{#unless}} do.

To the developers: get your heads out of the sand. Seriously. You can see that there's demand for a proper if-statement (and I intent to use the word 'demand' quite literally) so go and implement it, instead of whining about logiclessness. If you want you templates to be logicless, do away with ALL logic, including {{#if}} and {{#each}}.

JUST implement a proper if-statement. Folks who strongly believe in their logiclessness, shall opt not to use it. Simple. As. That.


Reply to this email directly or view it on GitHub.

Thanks for that, but the solution should be in the core package. The term "ifTest" is presumably only because Handlebars hijacks the term "if" before you can use it.

Another thing is that your ifTest takes a string, and does the evaluation of that string in runtime, whereas if a proper if-block would be in the core package, it could be in the compiled template (which is exactly one of Handlebars' strong points - one that I don't like throwing overboard by using eval() for ifs and elses)

You are 100% correct. Just using the tools available to me at the time.

Regardless, it works.

On Oct 5, 2013, at 3:41 PM, thany [email protected] wrote:

Thanks for that, but the solution should be in the core package. Also, the term "ifTest" is presumably only because Handlebars hijacks the term "if" before you can use it. Another thing is that your ifTest takes a string, and does the evaluation of that string in runtime, whereas if a proper if-block would be in the core package, it could be in the compiled template (which is exactly one of Handlebars' strong points - one that I don't like throwing overboard by using eval() for ifs and elses)


Reply to this email directly or view it on GitHub.

Just stumbled upon this thread while searching for comparison in Handlebars. I think you should either remove / rename the {{#if}} and {{#each}} blocks, or implement a proper if statement. It is a basic feature for every language. Period. If you really want logic-less templates, why don't you just use Moustache instead?

I understand that there is an opinion among developers that templates should be readable by non-develeopers (i.e. designers). But A) I have never worked with a designer where this was an issue, and B) I think the apporach should be that a generic solution is available built-in, and as extension you can use the boolean-only check, so you have a choice. Plus, adding helpers like {{#ifValueEqualsA}} and {{#ifValueEqualsB}} will force you to create a lot of boilerplate code that is just simply not needed. I work in a not-that-big mobile project and I have already 200 lines of code that just add comparisons for specific needs. That goes against (hopefully) every developers mindset that things should be as generic as possible.

@cal127 "I believe that you simply can't consider a single if/unless (without conditionals) as logic" - So what's the problem then? Why is checking an expression more logic than checking a boolean value? It's a check. Period. That is the logic that is done here, not the expression (since a boolean value is - guess what- an expression). Of course, assuming that the expression represents not business-, but UI logic.

I am sorry the idea of logic-less template engines seems already moribund...i dont see this still going in the the future. Developers need tools that makes things easier and faster not more complicated.

@thany rocks. I came about mustache(another logic-less template lang) yesterday and this was exactly the question that popped in my head few moments later. How did programmers ever think this is cool. This only makes matters worse. Programming paradigm i know is "separation of BUSINESS logic from PRESENTATION logic". That def means there is logic in presentation (views that contain/include templates in a pattern like mvc for example). How come they are trying to negate that and removing logic from presentation.

Scenario: I am running a loop in a view and i want to perform an action after x iterations. With handlebars i have to now go create a helper and then use in the loop right? how does this make my life easier? What happened to if count==x????? How is that better than using a language like php itself for your templating? How does it help design over logical template engines?

Me? No logic-less anything for a logic oriented job. Sorry!

I can't believe how ignorant you can be, dear believers in logicless. It's just not a reality, it's a complete myth, a fallacy, a false religion. No template more than a few lines will ever be entirely logicless. It's just simply not practical.

Now, to enforce such a belief onto your users is entirely your decision. But to keep brushing off any demand for logic is proof of stupidity and ignorance. Especially in this particular case, since there's already an amount of logic possible, albeit miniscule.

Again, I strongly urge you to reconsider. No, wait, don't reconsider. Just listen and do the right thing. Folks that don't want any of that silly logic in their templates, can go ahead and continue their wicked ways and jump through all kinds of hoops in order not to use logic.

Extending the if-block to do proper comparisons does not take away its current use. It will not make trouble for those who have not yet seen the logical light, those people may continue to code as they were.

It's not about cool; you yourself use separation of logic from presentation as a argument then ignore it to ask for your life to be simplified. You could have added any of the standard handlebars template libraries to your project or written your own.

You or nobody else has addressed any of the numerous arguments against this in any of the numerous threads. Just so that those arguments are clear in this thread:
1) You will be disrupting an existing ecosystem; which will cause conflicts and reworks for teams who want to update but have had their own IF for ~2 years.
2) There are existing helper libraries that will add the if you need, along with all the other helpers you'll ask for next.
3) As soon as it is agreed to add this 'if', the new argument will be the implementation of it. Name. Syntax. Arguments. You may promise to be happy with the if that shows up, but others won't. There will immediately be a new thread(s) here arguing it should work some other way.
4) The existing 'if' is exactly what should be there for -rendering-. "Display X if Y is present". It's not about business logic; which should happen in your model (I suggest Backbone, then you can have whatever you want your if to be, to just be an isXXX() method on your model).

Since we're asking each other for things, please don't continue this if you don't have a pretty good technical argument for making a major change. Being frustrated is silly - Add the 'IF' you want and be done.

1) No you will not. If you don't do anything, templates should remain working. Of course everything should be backwards-compatible. And even if it isn't, then simply don't upgrade.
2) An if-statement is elementary. What you're saying is like wheels on a car are now optional.
3) Syntax of an if statement is of very little importance. Every single programming language has one, and every one of them does exactly the same thing. So pick one and it will be fine. More importantly, having ANY proper if-statement is better than what we have now.
4) Wrong, search upwards for "template logic".

As for your last stance, the argument _has_ been made, and it's sound. It's been argued upon time and time again, but it really does seem like a religion. Unbreakable, and yet so fragile.

George Frick -

1) How is this different from upgrading ANY other framework or library that has ever existed ever?
2) You're right. Though, manually adding these basic features shouldn't be necessary for something so fundamental and necessary.
3) That's what Pull Requests are for.
4) You completely missed the point. No one on this thread is arguing for business logic in the view layer. We're arguing for USEFUL display logic in the view layer. The "if" given is not a true if, making it confusing to anyone who has ever used a programming language ever. It's more of an "exists".

If you think adding this would cause people to use business logic in templates, you're probably right because you can't fix stupid. Just because someone CAN do something bad doesn't mean you should prevent other people from doing something good (and necessary) in the process.

On Nov 22, 2013, at 3:55 PM, George Frick [email protected] wrote:

It's not about cool; you yourself use separation of logic from presentation as a argument then ignore it to ask for your life to be simplified. You could have added any of the standard handlebars template libraries to your project or written your own.

You or nobody else has addressed any of the numerous arguments against this in any of the numerous threads. Just that so that arguments are clear in this thread:
1) You will be disrupting an existing ecosystem; which will cause conflicts and reworks for teams who want to update but have had their own IF for ~2 years.
2) There are existing helper libraries that will add the if you need, along with all the other helpers you'll ask for next.
3) As soon as it is agreed to add this 'if', the new argument will be the implementation of it. Name. Syntax. Arguments. You may promise to be happy with the if that shows up, but others won't. There will immediately be a new thread(s) here arguing it should work some other way.
4) The existing 'if' is exactly what should be there for -rendering-. "Display X if Y is present". It's not about business logic; which should happen in your model (I suggest Backbone, then you can have whatever you want your if to be, to just be an isXXX() method on your model).

Since we're asking each other for things, please don't continue this if you don't have a pretty good technical argument for making a major change. Being frustrated is silly - Add the 'IF' you want and be done.


Reply to this email directly or view it on GitHub.

@thany
There is a difference between disproving an argument and dismissing it. "WRONG" equates to "NUH UH!".
Try not to be so personal about it either.

@tniswong
1) It isn't, this same holds true in any framework.
2) If you apply this in a general sense, Node should include all of its components. That they are fundamental or necessary can be argued but would lead to the idea that grouping them all together outside of the standard framework is good abstraction and separation. Many projects just don't need any of them, and others need special versions. So you can plugin a standard set, write your own, or use none. There isn't (again) any technically sound reason for all of these helpers to be rolled in by default.
3) Your statement doesn't in any way negate the original point, in fact - you help it. 20 pull requests to fix If. I'll bet the dev team will love going through them.
4) Exactly, it's an 'exists'. Render this if it exists.
When you can't write about 'anyone ever', it takes a single counter example. _raises hand_.

From the above notes it seems to me that one of the following is necessary:

  1. Rename if to exists and stop calling handlebars "logic-less" (because it's not)
  2. Add support for if to behave as an if statement.
  3. Remove if entirely.

I'd be happy with any one of those options.

Don't forget {{#unless}}

On Nov 22, 2013, at 4:40 PM, Aaron M [email protected] wrote:

From the above notes it seems to me that one of the following is necessary:

Rename if to exists and stop calling handlebars "logic-less" (because it's not)
Add support for if to behave as an if statement.
Remove if entirely.
I'd be happy with any one of those options.


Reply to this email directly or view it on GitHub.

I think what this really boils down to is summed up nicely by Aaron.

  1. There is a hypocrisy that needs to be addressed by claiming to be logic-less AND supplying an if/unless.
  2. The given "if" is a misnomer.

Fix them both, and this argument goes away.

On Nov 22, 2013, at 4:43 PM, Todd Niswonger [email protected] wrote:

Don't forget {{#unless}}

On Nov 22, 2013, at 4:40 PM, Aaron M [email protected] wrote:

From the above notes it seems to me that one of the following is necessary:

Rename if to exists and stop calling handlebars "logic-less" (because it's not)
Add support for if to behave as an if statement.
Remove if entirely.
I'd be happy with any one of those options.


Reply to this email directly or view it on GitHub.

@georgefrick
I was dismissing his argument simply because it has been disproven a million times before. We've been over this for far too long, and it must end. The if-statement must be added, noone will be disadvantaged, and everyone will be happy. Not wanting it is the same as not wanting airconditiong in ALL houses. I'll be the judge of what I want in my house. If it's in yours and you don't want it, then leave it be. Simple as that.

@webgovernor
No renaming needs to be done. A proper if-statement can be made fully compatible with the current one. Currently it's just "if boolean then...", and any fully-featured if-statement will do exactly that, only that boolean thing can now be any expression rather than just the one variable.

@tniswong
How nice of them, right? To add a filthy extra tag because the if-block as they implemented it is so oversimplified that it can't even negate an expression. But in a future Handlebars, the unless tag may simply become an alias for "if not". Kinda like do..while versus while..do in programming, where the two exist primarily for readability and not _really_ for any technical reason.

I, too, wish for basic comparisons in Handlebars. I understand the logicless philosophy. I also believe basic comparison support would be more intuitable and allow users to work more efficiently. If users in mass are moving basic comparison logic to a helper, this philosophy isn't doing them a favor or dissuading a perceived suboptimal behavior—it's just creating more work.

@jeremiahlee Not sure if you're agreeing or disagreeing with me there, I can read your comment either way :)

Either way, I've worked with Handlebars in the past, and I've requested for them to implement a proper if-block. This resulted in an avalanche of comments about a faux philosophy that logic should remain in the model. No Handlebars developer wished to think so much as a millimeter outside of their own tiny world (there is a rude word for that, but I'll skip it). Just look at this thread as proof.

This forced me to write a helper called "when" that does comparisons. Still no proper if-block construction, but close enough for me at the time. It did create a lot of unneccesary work for me though.

@thany: I agree that Handlebars should have basic comparison of two values built in. Logicless templates should not also be empathy-less.

I'll also vote for @thany's and the other arguments. The if else statements are way too basic.
Conditional classes and select boxes with pre-selected options should be doable with the default package of handlebars.

With nested helpers this is no longer an issue, e.g.

{{#if (greater-than array.length 3)}}
  ...
{{/if}}

good example @mmun :+1:

A bit odd, and I don't see any boolean combinators... But most of all, it doesn't change the overall standpoint of the maintainers of this project, which seems to be an unbreakable "NO LOGIC!!11!!1!1" kind of view.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

rhariraman picture rhariraman  ·  5Comments

LengYXin picture LengYXin  ·  3Comments

fcpauldiaz picture fcpauldiaz  ·  4Comments

janus-reith picture janus-reith  ·  3Comments

nknapp picture nknapp  ·  3Comments