Is there a better way to do this in handlebars?

352 Views Asked by At

Im using handlebars to spit out some static pages using a partial like so:

{{> component/card size="small" title="Card Title" }}

Now depending on the "size" of the card required, i need to set some different tailwind classes. Im currently doing it like so, but there must be a better way? Adding the class to the container and writing css is not an option.

{{setVariable "additionalHeadingClass" "text-5 md:text-6 mb-4"}}
{{#ifEquals size "small"}}
    {{setVariable "additionalHeadingClass" "text-4 mb-1"}}
{{/ifEquals}}
{{#ifEquals size "large"}}
    {{setVariable "additionalHeadingClass" "text-4 sm:text-5 md:text-8 mb-4"}}
{{/ifEquals}}
<h3 class="text-primary font-bold {{@root.additionalHeadingClass}}">{{title}}</h3>

and heres the helper im using:

Handlebars.registerHelper("setVariable", function (varName, varValue, options) {
    if (!options.data.root) {
        options.data.root = {};
    }
    options.data.root[varName] = varValue;
});
1

There are 1 best solutions below

2
76484 On

My opinion is that there is too much code in your template for what it actually does. Despite the intimidating number of lines, we really just want to map a size to a string of class names. I would also advise against the setVariable because I find it harder to think about when we creating a side-effect by manipulating a variable on our context object. I would much prefer a more functional-style helper, where we just give it the size and it returns the class names string.

I would create such a helper using a simple switch:

Handlebars.registerHelper('additionalClasses', function(size) {
  switch (size) {
    case 'large':
      return 'text-4 sm:text-5 md:text-8 mb-4';
    case 'small':
      return 'text-4 mb-1';
    default:
      return 'text-5 md:text-6 mb-4';
  }
});

And then we may reduce our template to the much simpler:

<h3 class="text-primary font-bold {{additionalClasses size}}">{{title}}</h3>

I have created a fiddle for reference.