abhilashlr
Posted on April 20, 2020
Originally posted at: https://abhilashlr.in/ember-refactor-templates
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"}}
...
{{/if}}
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.
Bonus 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_server1"}}
{{else if condition2}}
{{t "something_from_3rdparty_service"}}
{{else}}
{{t "generic_message"}}
{{/if}}
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).
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_server1"}}
{{~else if condition2}}
{{~t "something_from_3rdparty_service"}}
{{~else}}
{{~t "generic_message"}}
{{/if}}
And inspecting the rendered HTML in the Browser inspector shows
Here's a good read on the same: Whitespace Control.
Bonus 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.
Posted on April 20, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.