Encapsulate common behaviors with the aid of Angular directives

Wojciech Trawiński
JavaScript everyday
2 min readFeb 6, 2019

Today React cowboys are celebrating another release of the library which provides so-called hooks. I’ve heard that the hooks give a chance to easily reuse common logic.

In this post I’ll present how to achieve the same goal in Angular. The example is taken from a real world application.

Let’s say that you want to play a sound when a button within a navigation is clicked. The application contains several pages and each one has a navigation consisting of buttons.

Forget about DRY

If you forgot about the DRY (Don’t Repeat Yourself), you could accomplish the goal in the following way.

Create the service:

Of course, in a real world application I used a package called Howler to play sounds.

Render each page and register the click handler for each navigation’s button:

and define the playSound method within a component’s class:

Note, that I need to repeat the same code for each page, namely a callback definition and the callback registration for each button.

The need for refactor is clear!

Meet directives

Fortunately, you can encapsulate the common behavior, namely playing a sound upon click event, within a directive:

It’s far better than the initial solution, since you define the click callback just once. However, in order to apply the directive to a button, you need to add the appClickSound attribute to each button:

You’ve definitely improved the previous solution, since the click handler is defined in a single place. As a result, you can easily change the behavior and testing gets easier.

However, you can do better!

Use native selector

A directive’s selector can be any valid CSS selector such as an element selector. With the above code, the ClickSoundDirective instance will be applied to each button within the nav tag.

As a result, you no longer need to add an extra attribute to the navigation’s buttons:

Conclusions

It always puts a smile on my face when I hear React cowboys celebrating new features which has already been present in the Angular framework 😃

--

--