Directives in Angular
Tags: angular, typescript, webdev
Published: 2022-05-02 06:46:36


## Directives in Angular

Directives in angular are kind of utilities that adds additional behaviour to elements.

### There are three types of directives

 1. [Components](https://angular.io/guide/component-overview)

 2. Attribute Directives

 3. Structural Directives

### Components as Directives

Every Angular component contains a selector. By using the selector you can include it in other components. A component is a kind of directive which also has a template attached to it.

![Angular component](https://cdn-images-1.medium.com/max/2000/1*sQVOb6DOqpD1AWH8XbcHsw.png)

![Including a component using a selector](https://cdn-images-1.medium.com/max/2000/1*BJVc1nSzZ8fYOeAy8a0jdQ.png)

### Attribute Directives

Attribute directives modify the behaviour of other HTML elements, attributes, properties, and components. It can also listen to changes in its host.

You might have come across some built-in attribute directives such as ngClass, ngStyle, ngModel.

### Building an attribute directive

Using Angular schematics, We can generate an Angular directive by executing

ng generate directive make-bold

The directive needs to be added to the declarations in the module.

![App module](https://cdn-images-1.medium.com/max/2000/1*n8qGcr5dJRUiHm4_7lHAzQ.png)

Now, Let’s use the directive. We will use the directive in a paragraph to make the text bold. The way we do it is providing the selector of the directive as a attribute in the element.

![Paragraph tag with the directive](https://cdn-images-1.medium.com/max/2000/1*Yz3Bm4xC19wWqDN-W5mA3g.png)

To make the text bold, We need to access the paragraph element and set it’s style. We will access the element using ElementRef from @angular/core.

![Access the element and setting it’s style](https://cdn-images-1.medium.com/max/2040/1*RL9iZXo2BgUFkq6pOSnrpA.png)

### Listening to the host element

We can listen to the host element’s state using the HostListener decorator provided from @angular/core.

Let’s build a directive name ‘hover-border’ that styles an element whenever it is hovered.
>  Offcourse we can do all these just using CSS classes but to demonstrate the possibilities of an Angular directive, we are styling using the directive.

![Hover border directive](https://cdn-images-1.medium.com/max/2332/1*HJqFxEezBIr3GG3ZLvB8MA.png)

The hover directive will look something like this. We have used the HostListener to listen to ‘mouseenter’ and ‘mouseleave’ events of the host and change it’s style accordingly.

The host element will look something like this.

![host-element](https://cdn-images-1.medium.com/max/2016/1*VUcLsNNUGGBzv3flTZZzTg.png)

The end result:

![Result of make-bold and hover-border directive](https://cdn-images-1.medium.com/max/2000/1*JCB690aixIzUHLlKGdhAcw.gif)

### Passing values into Directives

We can pass values from the host element to the directive. We will use the Input Decorator provided from @angular/core.

Let’s say we want to pass the border color to the hover-border directive. We are gonna create a Input variable name ‘appHoverBorder’ ( same name as the directive selector) and set a default value ‘black’.

We are going to modify the mouseenter procedure to show the border color provided into the directive.

![app-hover](https://cdn-images-1.medium.com/max/2000/1*wyWztBKcv3F_ZeIk__z55w.png)

![app-hover](https://cdn-images-1.medium.com/max/2712/1*Ay2SdoEQdFo1W3wPSlxIug.png)

The motive of setting the name of the variable same as the directive selector is to provide the border color to the directive itself.

![directive](https://cdn-images-1.medium.com/max/2316/1*Ww1okm85voS0bNfXGBdSzA.png)

Now, If we want to another configuration to the directive. Let’s say the border width. We can create another input variable named ‘borderWidth’ in the hover-border directive.

![directive](https://cdn-images-1.medium.com/max/2000/1*qIbimwDqm91qAyrKpp9Krg.png)

![directive](https://cdn-images-1.medium.com/max/3240/1*yamJWAkSH58972fFTddpCQ.png)

![directive](https://cdn-images-1.medium.com/max/2000/1*kdeaM2qBDGh0VLGHGdqtXQ.png)
>  The purpose of creating another variable just for the borderWidth is just demonstrating how to have multiple Input variables in a directive. 
Ideally I would create a config variable for the directive. Let’s say { borderColor: string, borderWidth: string}

### Using HostBinding to change change host element’s properties

We can bind a particular property of the host to a directive’s variable and change the value directly.

![Host binding](https://cdn-images-1.medium.com/max/2000/1*Pz0wBqI3o5yUXhJ16jVOWw.png)

![directive](https://cdn-images-1.medium.com/max/2000/1*OhqitFySYFVN_qLNGOgWHg.png)

### Structural Directives

Structural directives are the directives that can manipulate the DOM Structure.

Angular provides a few built-in structural directives that you may have already come across.

NgIf, NgForOf, NgSwitch etc. See more in [Built-in directives](https://angular.io/guide/built-in-directives)

### Building a custom structural directive

We are going to create a structural directive which will receive a ‘userRole’ and a set of ‘Roles’. If ‘userRole’ consists in the List of ‘Roles’ then we will show the Element on which we have applied the directive.

Let’s name the directive as ‘if-roles’

ng generate directive if-roles

![if-role directive](https://cdn-images-1.medium.com/max/2368/1*UjwDl5iKce4uumCjrGdHcQ.png)

The usage in an element:

![directive](https://cdn-images-1.medium.com/max/2192/1*LKW394ma9Q9KzYpxGGdlLw.png)

If-role Directive:

We are injecting TemplateRef<any> and ViewContainerRef in the contructor.

templateRef is the element that you have applied the directive to.

viewContainerRef is the container for the element.

So, when you apply a structural directive into an element. A viewContainer get’s created which has to ability to render the element(templateRef) within it’s container.
>  What about the * before the directive?
>  The asterisk, *, syntax on a structural directive, such as *[ngIf](https://angular.io/api/common/NgIf), is shorthand that Angular interprets into a longer form. Angular transforms the asterisk in front of a structural directive into an [<ng-template>](https://angular.io/api/core/ng-template) that surrounds the host element and its descendants.

As you might noticed that you can only specify one value/expression into the directive *directive=”value”

How do we provide some extra context to the directive such as ‘Roles’ in these case?

We are gonna create another Input whose name will be appIfRolesValues

For any secondary Inputs the pattern for their name has to be

{directive}{inputName}

The way we provide the secondary input to the directive is by using this pattern

*directive=”value;inputName”

In our example, we did

*appIfRoles=”’angularDev’; values: [‘angularDev’, ‘webDev’]”

There are a few advanced topics in structural directives such as

[Structural directive syntax](https://angular.io/guide/structural-directives#structural-directive-syntax-reference)

[Improving template type checking for custom directives](https://angular.io/guide/structural-directives#improving-template-type-checking-for-custom-directives)

I will be covering these in separate articles.

You can find the source code in given link: [https://stackblitz.com/edit/angular-ivy-uoqa3h](https://stackblitz.com/edit/angular-ivy-uoqa3h)

I hope this article helped you to get started with Angular directives. If you have any queries or doubts, feel free to reach out to me in the comment box.