Skip Repetition in Angular Templates with Custom Directives

Angular Aug 30, 2021


At Halodoc, we have so many web applications and most of them were built with Angular. We have already been using Angular for 5 years, with that experience we always strive for the best practices and try to maximize the use of features from Angular. From this article, I’m going to explain what Custom Directive is and how we can use Custom Directive for most of the stuff we usually use in Web Development.

Directives in Angular

A Directives is essentially a function that runs whenever the Angular compiler locates it in the DOM. Angular DOM manipulation features you're probably familiar with, such as ngClass, ngIf, and ngFor , are directives. You may also create your directives that can be called with whatever name you choose with your own specific functionality of course. There are 3 forms of Angular Directives that I will explain below.

Components

Components are actually directives with templates. Structural and Attributes Directives don't have templates. The only difference for Components between Structural Directives and Attributes Directives is the templates. So, in short, Component is a more polished version of Directives.

Attributes Directives

Attribute directives change the behaviour and appearance of the document object model (DOM). Attributes Directives have the same appearance as standard HTML attributes. Attribute directives only affect or change the element they are added to.

Standard HTML Attributes
darkOverlay as Attributes Directives 

Structural Directives

While Attribute Directives only affect the element they are added to, Structural Directives affect a whole area in the DOM since Structural Directives allow elements to be added or removed. Structural Directives also have the same appearance as standard HTML attributes but with a leading *. The asterisk symbol is telling Angular to surround the host element into an <ng-template>.

duplicateFor directives
duplicateFor as Structural Directives
How Angular Interprets Structural Directives

Why Custom Directives

We can make work more efficient by using custom directives because we don't have to rewrite code in different components. For example, while dealing with a large number of autosearch input forms that require debounce. Simply write a custom directive that serves as a debounce for use in other components or maybe you want to hide certain elements if the pointer is not focused on that element, that is also can be achieved with custom directives.

Create Your Custom Directives

For this example, we will try to build our own custom directives that serve as a debounce for input events.

First, let’s create a new directive file with angular-cli:

ng generate directive debounce

Debounce Directive 

After we created the file we can register it to our app.module.ts. For the selector name this time we use debounceSearch you can change the selector name whatever you want but remember to always make it meaningful for the best practices sake. The outline for this directives would be something like this:

  • Set up HostListener to listen to input events.
  • Make a function that debounce the event after a number of milliseconds
  • Emit Event to marks that debounce process has finished

So, now we need to set up the events listener with HostListener Decorator and the method to execute if the listener received the input events.

HostListener on Directive

On the image above, the inputEvent method call .next() to have the Subject emit the next value. We use Subject from RxJS to listen to events. We also use the RxJS function operator called debounceTime. This enables us to debounce the event depending on a specified number of milliseconds on the Subject events. In the next step, we use Angular Decorator @Output with EventEmitter class to allow us to create custom events. We also create a method to debounce the input.

Full Debounce Input Directive

On the above code we already completed our Debounce Input Directive, we also set the debounceTime to be 1000 milliseconds. It means after 1000 milliseconds of not typing, our directive will emit the afterDebounce event. We can now use our directives in our template as seen below.

Directive Usage‌‌

Now when we type on the input element, it is debounced by 1000 milliseconds. After 1000 milliseconds of not typing, the afterDebounce event will fire and the searchData() method will be called. For your projects, you can also use the @Input Decorator to specify your debounceTime so you can change it for each input element, just be creative.

Summary

Directives are basically custom attributes that instruct Angular to change the style or behavior of the DOM components on which they sit. In addition, we understand the distinction between the characteristics directive and the structural directive. Custom directives are used to reduce repetitive effort and make the code cleaner and more efficient.

Join us

Scalability, reliability and maintainability are the three pillars that govern what we build at Halodoc Tech. We are actively looking for engineers at all levels and  if solving hard problems with challenging requirements is your forte, please reach out to us with your resumé at careers.india@halodoc.com.


About Halodoc

Halodoc is the number 1 all around Healthcare application in Indonesia. Our mission is to simplify and bring quality healthcare across Indonesia, from Sabang to Merauke. We connect 20,000+ doctors with patients in need through our Tele-consultation service. We partner with 3500+ pharmacies in 100+ cities to bring medicine to your doorstep. We've also partnered with Indonesia's largest lab provider to provide lab home services, and to top it off we have recently launched a premium appointment service that partners with 500+ hospitals that allow patients to book a doctor appointment inside our application. We are extremely fortunate to be trusted by our investors, such as the Bill & Melinda Gates Foundation, Singtel, UOB Ventures, Allianz, GoJek, Astra, Temasek and many more. We recently closed our Series C round and In total have raised around USD$180 million for our mission. Our team works tirelessly to make sure that we create the best healthcare solution personalised for all of our patient's needs, and are continuously on a path to simplify healthcare for Indonesia.