5

Is there a way to shorten

{{#if arg1}}
    {{#if arg2}}
        //stuff
    {{/if}}
{{/if}}

to just a single if?

{{#if arg1 arg2}}
{{#if arg1 && arg2}}

Both of the above don't seem to work.

Sinistralis
  • 412
  • 3
  • 16
  • I discovered I can use UI.registerHelper(), however I am unsure how to configure this to take in any number of arguements. (Arrays do not seem to work, have yet to try maps) – Sinistralis Nov 04 '14 at 21:28

2 Answers2

8

Spacebars continues the philosophy of Mustache and Handlebars being logic-less template languages. This is why even simple logic is best placed in the controller rather than in the template.

You can, however, define a custom block helper that performs a logical and.

<template name="ifand">
  {{#if arg1}}
    {{#if arg2}}
      {{> Template.contentBlock}}
    {{else}}
      {{> Template.elseBlock}}
    {{/if}}
  {{else}}
    {{> Template.elseBlock}}
  {{/if}}
</template>

Call as:

{{#ifand arg1="foo" arg2="bar"}}
  // stuff
{{/ifand}}

You can also learn more about passing variables into templates.

For the general case (and among an arbitrary number of arguments), you'll want to register a global template helper:

Template.registerHelper('and', function () {
  var args = Array.prototype.slice.call(arguments, 0, -1);  // exclude key=value args
  var parameters = arguments[arguments.length - 1];  // key: value arguments

  return _.every(args, function (arg) {
    return !!arg;
  });

});

Call as:

{{#if and 1 "foo" 3 'bar' param="test"}}
  True
{{else}}
  False
{{/if}}
Community
  • 1
  • 1
Dan Dascalescu
  • 143,271
  • 52
  • 317
  • 404
  • I know how to pass variables into templates, what worries me about this approach is it isn't capable of handling X arguements. I need a number of different templates to perform essentially the same task. Being able to define my own helpers feels like the correct route to go, but I do not understand how passing variables into the helper works, unless it has the same problem of only being able to handle a single variable. – Sinistralis Nov 04 '14 at 21:38
  • Can you not define Template successfully in the lib folder? If not, where is the best place to put global Template helper definitions? – Sinistralis Nov 05 '14 at 15:28
  • 1
    I'd put them in `/client/lib`. `Template` should be defined there. – Dan Dascalescu Nov 05 '14 at 22:25
  • 1
    That's a good idea. I'll make a note of that for my standards. Thanks for all your help good sir. – Sinistralis Nov 06 '14 at 05:57
1

While within a template, you are able to use the this object to reference arguments passed in, which lets me avoid having to use multiple #if arguements in most of the cases I need them in.

Template.myTemplate.created = function() {
    if(this.data.arg1 && this.data.arg2) {
        //do JS setup here
    }
}

Additionally, helpers can be specified using

Template.registerHelper('exists', function() {
    if(this.data.arg1 && this.data.arg2) {
        return true
    }
}

and you execute the above helper as such

{{#if exists}}
    //stuff
{{/if}}

{{> myTemplate arg1 arg2}}

I just stumbled on this by accident but this is a HUGE find for me.

Sinistralis
  • 412
  • 3
  • 16
  • 1
    I believe [UI.registerHelper is, being deprecated](https://github.com/meteor/meteor/issues/3017). Please check my updated answer. – Dan Dascalescu Nov 04 '14 at 23:15
  • I tried using Template.registerHelper, and it kept telling me that Template was undefined. This is odd. If this is the case, I need to figure out why it isn't working for me and update this accordingly. – Sinistralis Nov 05 '14 at 15:02
  • Updated this to reflect your information so I don't spread information. Please see my comment on your answer though, as UI exists during lib definition but Template does not and I feel like lib is where I should be defining my global helpers. – Sinistralis Nov 05 '14 at 15:29
  • I tried this out and it didn't work for me. I didn't even see a data property off of the .this context. I tried this for example {{> myTemplate "country" "label for country" "true" "another string with spaces" true}}. Then Template.registerHelper('exists', function ([no parameters?]) { if (this.data.arg1) { return true } }); There is not this.data, what is the arg1 in my case? How do I refer to "country" for example? I looked at the locals in debug, there is no "country". Thanks for this tip by the way. I hope it works as I usually have to build a dummy helper that's just a pass-through – Aaron Nov 12 '14 at 14:48
  • I don't know what .data isn't being exposed to you (and I assume is why there are no args in that function call, because you reference the args through .data). Are you using Meteor 1.0X? – Sinistralis Nov 24 '14 at 16:19