What's the best way to handle a switch case in a template (eg: a button with 4 possible states)? It seems wrong to pull the html out into a helper, but it feels just as bad to put the logic into the template...
Edit:
As you can see, putting the html in a helper is far from ideal, but changing a class, a tag-name, properties, and content, would make the template wholly unreadable.
Template.nextMeetup.helpers({
rsvpButton: function(rsvp) {
var button;
switch(rsvp){
case 'yes':
button = '<a ' + this.event_url + 'class="rsvp btn btn-success pull-right" title="visit event page" target="_blank"><i class="icon-check"></i> I\'m Attending</a>';
break;
case 'maybe':
button = '<a ' + this.event_url + 'class="rsvp btn btn-warning pull-right" title="visit event page" target="_blank"><i class="icon-warning-sign"></i> I might go</a>';
break;
case 'no':
button = '<a ' + this.event_url + 'class="rsvp btn btn-danger pull-right" title="visit event page" target="_blank"><i class="icon-remove"></i> I\'m not going</a>';
break;
case 'none':
button = '<a ' + this.event_url + 'class="rsvp btn btn-inverse pull-right" title="visit event page" target="_blank"><i class="icon-spinner"></i> I havn\'t decided</a>';
break;
default:
button = '<button class="rsvp signIn btn btn-disabled pull-right">Sign in to RSVP</button>';
}
return new Handlebars.SafeString(button);
}
});
Within Meteor, templates are used to create a connection between the project’s interface and the project’s JavaScript code. When we place interface elements inside a template, such as a button or a form, we’re able to reference those elements and build an interface that users can interact with.
This Method is callable from the client and server using Meteor.call. Note that you should only use a Method in the case where some code needs to be callable from the client; if you just want to modularize code that is only going to be called from the server, use a regular JavaScript function, not a Method.
Error handling. In regular JavaScript functions, you indicate errors by throwing an Error object. Throwing errors from Meteor Methods works almost the same way, but a bit of complexity is introduced by the fact that in some cases the error object will be sent over a websocket back to the client.
Methods are Meteor’s remote procedure call (RPC) system, used to save user input events and data that come from the client. If you’re familiar with REST APIs or HTTP, you can think of them like POST requests to your server, but with many nice features optimized for building a modern web application.
Not sure what you’re trying to output, but a helper that evaluates equality will likely be involved. Put this in one of your project’s client-loaded JavaScript files:
Template.registerHelper("equals", function (a, b) {
return (a == b);
});
Then you can create something similar to a switch-case structure using if
blocks and your new equals
helper. For example, if you're storing the state of a button in a variable named btnState
and the possible values are 1
, 2
or 3
:
<button class="{{#if equals btnState 1}}btn-active{{/if}}
{{#if equals btnState 2}}btn-inactive{{/if}}
{{#if equals btnState 3}}btn-disabled
{{else}}btn-default{{/if}}">
If you want switch
-case
's ability to short-circuit further tests after it hits a true value, and/or a default case at the end, the way to do so is with an ugly set of nested if
-else
blocks:
<button class="{{#if equals btnState 1}}
btn-active
{{else}}
{{#if equals btnState 2}}
btn-inactive
{{else}}
{{#if equals btnState 3}}
btn-disabled
{{else}}
btn-default
{{/if}}
{{/if}}
{{/if}}">
This example is almost trivially simple; I’m assuming that you’re using this as a control structure for a large template, where instead of something like btn-default
you have dozens of lines of HTML.
If you really are using it for short snippets of text like CSS class names, you could instead create a helper that maps a set of cases with a set of strings to be returned. For example (CoffeeScript):
Template.registerHelper "switch", (input, cases, output, def) ->
# input is the variable we're comparing, i.e. switch(input)
# cases is an EJSON-stringified array, i.e. case "foo", case "bar"
# output is an EJSON-stringified array of strings to return for each case
# def (default) is a string to return if none of the cases are met
# Validate input, convert EJSON strings into arrays:
unless input? and _.isString(cases) and _.isString(output)
return ""
cases = EJSON.parse cases
output = EJSON.parse output
unless _.isArray(cases) and _.isArray(output) and
cases.length is output.length
return ""
# Evaluate each case, returning as soon as the first case is true:
for value, index in cases
return output[index] if input is value
# If we've made it this far, none of the cases were met; return def (default):
if def? and _.isString(def) then return def else return ""
And to use it:
{{switch btnState "[1,2,3]"
"[\"btn-active\",\"btn-inactive\",\"btn-disabled\"]" "btn-default"}}
Handlebars doesn’t allow passing arrays or objects into helpers, hence the contortions with JSON strings passed as parameters and then parsed.
Use one template per button and an additional dynamic template
Your template helper, returning the dynamic template:
Template.nextMeetup.helpers({
rsvpButtonTemplate: function(rsvp) {
switch(rsvp){
case 'yes': return Template.buttonYes;
case 'maybe': return Template.buttonMaybe;
case 'no': return Template.buttonNo;
case 'none': return Template.buttonNone;
}
}
});
Your main template, calling the template helper:
<template name="myPage">
...
{{> rsvpButtonTemplate}}
...
</template>
Your 4 buttons:
<template name="buttonYes">
<a {{event_url}} class="rsvp btn btn-success pull-right" title="visit event page" target="_blank"><i class="icon-check"></i> I'm Attending</a>
</template>
<template name="buttonMaybe">
<a {{event_url}} class="rsvp btn btn-warning pull-right" title="visit event page" target="_blank"><i class="icon-warning-sign"></i> I might go</a>
</template>
<template name="buttonNo">
<a {{event_url}} class="rsvp btn btn-danger pull-right" title="visit event page" target="_blank"><i class="icon-remove"></i> I'm not going</a>
</template>
<template name="buttonNone">
<a {{event_url}} class="rsvp btn btn-inverse pull-right" title="visit event page" target="_blank"><i class="icon-spinner"></i> I havn't decided</a>
</template>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With