Directives are a great way to increase your efficiency when composing templates. But just because they are available, it does not mean they should be used in every scenario. Misusing these can have performance implications and clutter your codebase. In this post, let’s take a closer look at the when directive and compare different conditional cases.
If you are not familiar with FAST directives, take a look here: Using Directives | FAST.
According to the documentation, the when
directive enables you to conditionally render blocks of HTML. In other words, it is another way of writing if (condition) { //do something }
.
Good use case
This is an example of using if (condition) { //do something }
to render our happyTemplate based on the value of the happy property :
With the when directive
, we can achieve the same condition check and reduce the if (condition) { //do something }
to just one line of code:
Doesn’t this small refactor make you happy?
The when directive
is great for the replacement of a single if (condition) { //do something }
. The value provided here is making the block of code less verbose.
How about performance? Let’s run some benchmarks comparing these two implementations.
NOTE: All benchmarks are run with fast-benchmarks, and the sample size for each benchmark is 50 with auto-sampling turned on. For a little more context, when we compare 2 versions, a minimum of 100 samples will be run in total. With auto-sampling set at 1 minute, samples will keep increasing until it hits the 1-minute mark.
local version — represents if (condition) { //do something }
master version — represents when directive
To summarize the results:
- The blue boxes indicate that between the 2 implementations, there was no statistical performance difference in javascript execution time and memory consumption.
- The green boxes show that
if (condition) { //do something }
bundle size turns out to be more than — 129.86kb compared to the 129.80kb —when directive
These results show that using the when directive
here provides better readability and slightly improved bundle size. This is primarily the purpose of the when directive
.
Here’s another way you might think to refactor the previous if (condition) { //do something }
without the when directive
by using the &&
operator :
This is also a valid and aesthetically pleasing implementation. Let’s run a benchmark to compare this with the when directive
implementation :
local version — represents &&
master version — represents when directive
To summarize the results:
- The blue boxes indicate that between the 2 implementations, there was no statistical performance difference in javascript execution time and memory consumption.
- The green boxes show that
if (condition) { //do something }
bundle size turns out to be more than — 129.82kb compared to the 129.80kb —when directive
Surprise, surprise! when directive
is still the winner here in terms of bundle size. When you want to render a template based on a single condition, this nifty when directive
is your go-to.
Given these results, the guidance here is to use the
when directive
to reduce overall bundle size (every byte counts!).
Bad use case 1
While the when directive
comes in handy in the previous scenarios; it does not provide optimizations in every scenario.
For example, just as you would not do something like this in your code:
You should not do this with the when directive
:
Let’s expand both these implementations and see how they look in the bigger picture, starting with the when directive
:
While there are no errors in this implementation, I hope you can see that this can quickly become unmanageable if more conditions are added. Additionally, by separating the two lines of when directive
code, it may make it seem like the 2 conditions are not related. This is just an if...else
statement, so we should write it as one.
Here’s one way to refactor this with the ternary operator
, and eliminating the when directive
.
This is arguably more readable than the previous when directive
example. Here are the benchmark results between the when_long_example.ts and if_long_example.ts:
NOTE: For this particular benchmark, the click event handler on the button is triggered 10x for each sample taken to switch between templates.
local version — represents ternary operator
master version — represents when directive
To summarize the results:
- The blue boxes indicate that between the 2 implementations, there was no statistical performance difference in javascript execution time and memory consumption.
- The green boxes show that
ternary operator
bundle size turns out to be less than — 130.82kb compared to the 130.88kb —when directive
Given these results, the guidance here is to use the
ternary operator
to reduce overall bundle size (every byte counts!).
Up to this point, you should get the idea that when directive
is valuable as a replacement for if (condition) { //do something }
. Outside of this scenario, it is not recommended when working with conditionals or dynamic templates.
Bad use case 2
Let’s look at some more examples to illustrate common misusage of the when directive
. Here’s how you might use the when directive
to handle templates that change depending on a series of conditions:
If you aren’t careful, you could easily make the error of displaying multiple templates at the same time with the when directive
(I made this mistake while drawing up this example).
Let’s summarize what we’re trying to achieve and think about a more effective implementation. Depending on what the emotionalLevel value is, we want to render the corresponding template:
0–1 depressed
2–3 sad
4–5 indifferent
6–8 happy
9–10 ecstatic
With a switch statement
you can define the numbers in a specific range, but with the when directive
you’d have to be more explicit. Check out the example below using the switch statement
:
This implementation is less error-prone and gives better context on how the emotionLevel relates to each of the templates.
Let’s do a quick sanity check with a benchmark run:
NOTE: For this particular benchmark, the click event handler on the button is being triggered 10x for each sample taken to switch between templates. The emotionLevel is incremented from 0–10.
local version — represents switch statement
master version — represents when directive
To summarize the results:
- The blue boxes indicate that between the 2 implementations:
A. There was no statistical performance difference in javascript execution time.
B. Memory consumption was faster with theswitch statement
compared to thewhen directive
- The green boxes show that
switch statement
bundle size turns out to be less than — 130.94kb compared to the 131.01kb —when directive
Given these results, the guidance here is to use the
switch statement
to reduce overall bundle size (every byte counts!) AND memory optimization.
The fun does not have to stop here, you can keep thinking of cleaner ways to refactor your code where it makes sense. For example, if you prefer your template to be less cluttered, you can move the switch statement
into its own method and use a map
to find the template that matches the condition.
This would undoubtedly result in more code, and running a benchmark confirms that bundle size increases. See below:
NOTE: For this particular benchmark, the click event handler on the button is being triggered 10x for each sample taken to switch between templates. The emotionLevel is incremented from 0–10.
local version — represents map
master version — represents when directive
To summarize the results:
- The blue boxes indicate that between the 2 implementations:
A. There was no statistical performance difference in javascript execution time.
B. Memory consumption was faster with themap
solution compared to thewhen directive
- The green boxes show that
map
bundle size turns out to be more than — 131.25kb compared to the 131.01kb —when directive
Given these results, the guidance here is to still use the
switch statement
in the template over themap
andwhen directive
solutions if you want both the benefit of smaller bundle size and memory optimization.
While this may not be the most optimized implementation for this particular scenario, if your switch statements become longer, the results could quickly shift to favor the map
solution. It’s important to be able to adapt to different scenarios.
In summary, when you are simply working with a single if statement
in your template, you should be using the when directive
. On the other hand, when you have more complex conditional situations, it is better to omit the use of the when directive
!
Performance results can fluctuate depending on how complex your conditionals or templates become. If you keep this in mind, you can continue to improve the codebase you are working on.