Refactoring Ember templates - Quick tip!

4 min read • 18th March 2020
Refactoring complex template logic

Some of us might have written complex if-else logic in our Ember templates (a.k.a HTMLBars templates). There could be scenarios where certain lines of code look almost similar, but we keep them as-is for readability. Perhaps, writing a shorter version of it makes the entire file readable with concise LoC. Let's assume a simple bootstrap-like HTML + text content (using translations):

{{#if isInfo}}
  <i class="icon-info"></i>
  {{t "info.title"}}
{{else if isWarn}}
  <i class="icon-warn"></i>
  {{t "warn.title"}}
{{else is isDanger}}
  <i class="icon-danger"></i>
  {{t "danger.title"}}
  <i class="icon-success"></i>
  {{t "success.title"}}

Now the problem with this LoC is readability in itself if there were similar HTML all around this page's template file. In such cases, you can opt for a computed property that finds the right key and use it on the template. Something like below:

<i class="icon-{{type}}"></i>{{t (concat type ".title")}}

Amazing, now we have 13 lines shortened to 1 line.

Link to this sectionBonus Tip 1

Let's say you have no control over the t helper's key and that it would be a specific use case based on your API or 3rd party services.

In such scenarios, one way is to optimise this in your JS code, based on switch conditions and decide which key you would want to use. That would be unit-testable code base. Let's say you would want to do this if-else in the template like the following:

<i class="icon-alert margin-right-20"></i>
{{#if condition1}}
  {{t "something_from_api"}}
{{else if condition2}}
  {{t "something_from_3rd_party_api_uncontrollable"}}
  {{t "generic_message"}}

If you notice a bit closer, there is a class called margin-right-20 on the icon. Generally, icon + text lines on the UI tend to have a minor space between them. Since our templates use a sequence of if-else conditions, this internally introduces whitespace around the moustache ({}) code that is present. And if you see closer on the UI, the icon + text would end up having a 20px margin on the right and a white space introduced just before the TextNode (generated by the translation helper).

Complex lines of code with if else logic

Like I said before, one way to fix this is by generating the key on the javascript side and rendering the same in a single line. Or if you still like to do this on your template, you can use the ~ character by the braces, something like below:

<i class="icon-alert margin-right-20"></i>
{{~#if condition1}}
  {{~t "something_from_api"}}
{{~else if condition2}}
  {{~t "something_from_3rd_party_api_uncontrollable"}}
  {{~t "generic_message"}}

And inspecting the rendered HTML in the Browser inspector shows

Complex lines of code with if else logic

Here's a good read on the same: Whitespace Control.

Link to this sectionBonus Tip 2

If the same HTML of icon and text's parent holds a display: flex or display: inline-flex, despite whitespace being present, it would not be visible on the UI output.

Here's a twiddle for you to try.

Enjoyed this article? Tweet it.

I guess you might be looking to add your comments? Glad to tell you that this section is under construction. But don't hold on to your thoughts! DM them to me on Twitter