DEV Community

Cover image for Building Reusable Components with Angular Directives
josematoswork
josematoswork

Posted on • Originally published at angulardive.com

Building Reusable Components with Angular Directives

Building Reusable Components with Angular Directives

If you're building an application with Angular, there's a good chance that you're going to need to create some custom components at some point. Sometimes, these components are unique to a specific use case. However, there are often cases where we want to create a component that can be reused in multiple places throughout our application. This is where Angular directives come in handy.

What Are Angular Directives?

At a high level, an Angular directive is essentially a function that "directs" Angular to do something. These "somethings" usually take one of two forms:

  • Manipulating the DOM

  • Modifying component behavior

Directives are a powerful feature of Angular because they allow us to encapsulate behavior and logic into reusable pieces of code. Instead of needing to write the same code in multiple components, we can create a directive that can be used across our entire application. This can help us keep our codebase DRY and can significantly reduce the amount of code that we need to write.

Creating a Simple Directive

Let's start by creating a simple directive that will demonstrate how directives work. In this example, we're going to create a directive that will add a red border to any element that it's attached to.

<import { Directive, ElementRef } from '@angular/core';

@Directive({
  selector: '[appRedBorder]'
})
export class RedBorderDirective {
  constructor(el: ElementRef) {
    el.nativeElement.style.border = '1px solid red';
  }
}>

In this code example, we've created a directive called "RedBorderDirective". This directive takes an ElementRef parameter in its constructor. The ElementRef represents the HTML element that the directive is attached to. In the constructor, we're simply setting the element's border to be a red 1px border.

Now that we've created our directive, let's see how we can use it. Let's say that we have an Angular component that looks like this:

<import { Component } from '@angular/core';

@Component({
  selector: 'app-my-component',
  template: '<div appRedBorder>Hello, World!</div>'
})
export class MyComponent {}

In this example, we've created an Angular component called "MyComponent". Inside the component's template, we've added a div element and attached our "appRedBorder" directive to it. This will cause the element to have a red border.

Passing Data to Directives

Of course, our directive isn't very useful if it can't be customized in some way. Thankfully, Angular provides several ways to pass data to directives.

Using Input Properties

One way to pass data to a directive is using input properties. Input properties allow us to pass data to a directive when it is used on an HTML element. Let's modify our "RedBorderDirective" to take a color input:

<import { Directive, ElementRef, Input } from '@angular/core';

@Directive({
  selector: '[appBorderColor]'
})
export class BorderColorDirective {
  @Input() appBorderColor: string;

  constructor(el: ElementRef) {}

  ngOnChanges() {
    this.el.nativeElement.style.border = `1px solid ${this.appBorderColor}`;
  }
}

In this example, we've added an input property to our directive called "appBorderColor". This input property is of type string. When we use this directive on an HTML element, we'll be able to pass a color value to it. Inside the directive's constructor, we're not doing anything with the "el" parameter, so we can safely remove it.

In the ngOnChanges() method, we're updating the element's border color to match the value of the "appBorderColor" input property.

Now let's see how we can use this directive:

<import { Component } from '@angular/core';

@Component({
  selector: 'app-my-component',
  template: `<div appBorderColor="green">Hello, World!</div>`
})
export class MyComponent {}

In this example, we've updated our component's template to include our "appBorderColor" directive. We're passing the string "green" to the directive's input property, which will cause the element to have a green 1px border.

Using Attribute Directives

Another way to pass data to a directive is by using attribute directives. Attribute directives are directives that are applied to elements as HTML attributes. We can create an attribute directive by using the @Directive decorator's "host" property.

Let's create a new directive that will highlight the text inside an element. We'll call this directive "HighlightDirective". This directive will take a color input and will highlight the element's text with that color. Here's the code for our "HighlightDirective":

<import { Directive, ElementRef, Input } from '@angular/core';

@Directive({
  selector: '[appHighlight]',
  host: {
    '(mouseenter)': 'onMouseEnter()',
    '(mouseleave)': 'onMouseLeave()'
  }
})
export class HighlightDirective {
  @Input() appHighlight: string;
  
  constructor(private el: ElementRef) {}

  onMouseEnter() {
    this.el.nativeElement.style.backgroundColor = this.appHighlight;
  }

  onMouseLeave() {
    this.el.nativeElement.style.backgroundColor = null;
  }
}

In this example, we've created a new directive called "HighlightDirective". This directive takes a color input property, just like our "BorderColorDirective" does. However, instead of modifying the element's border, this directive modifies the element's background color.

In the directive's constructor, we're injecting the ElementRef, just like we did in our "BorderColorDirective". In the onMouseEnter() method, we're setting the element's background color to the value of the "appHighlight" input when the user's mouse enters the element. In the onMouseLeave() method, we're setting the element's background color back to null when the user's mouse leaves the element.

Now let's see how we can use this directive:

<import { Component } from '@angular/core';

@Component({
  selector: 'app-my-component',
  template: `<div appHighlight="yellow">Hello, World!</div>`
})
export class MyComponent {}

In this example, we've updated our component's template to include our "appHighlight" directive. We're passing the string "yellow" to the directive's input property, which will cause the element's text to be highlighted with a yellow background color.

Conclusion

Angular directives are a powerful way to create reusable components in your Angular application. Whether you're manipulating the DOM or modifying component behavior, directives allow you to encapsulate code into reusable pieces that can be used across your entire application. With input properties and host properties, you can easily customize your directives to fit your specific needs. By using directives in your Angular code, you can keep your codebase DRY and maintainable.

Top comments (0)