Angular 4 : Propagating events from directives to parent components.

The objective is of this content is to provide a "learn by example" on how to propagate events from directives to parent components in Angular 4. I'm briefly going to touch upon the following :

  • Decorators
  • Directives
  • Components

If you are already familiar with them, you may want to skip those basic briefs and go straight to Learn by Example.

What are Decorators?

The web is a special place that has special needs. Decorators are meta declarations that state that a declaration or a member is something more than just a ....declaration or a member It allows developers to expand on the general Javascript dialect.

"Hey! I'm not just a class, I'm something more than a class!'.

Click here to learn more about decorators


What are Directives?

Directives are mechanisms that attach specific event listeners to the dom. They are characterized by either attributes or tags depending on the type of a directive you decide to use. There are 3 types of directives: component, structural, attribute.

Component Directives

Components—directives with a template.

Structural Directives

Structural directives change or modify the structure of the HTML dom.

Attribute Directives

Attribute directives change the aesthetics of the dom.

Click here to learn more about Angular 4 directives.


What are Components?

Components are the building blocks of the application.

Click here to learn more about Angular 4 components.


Learn by Example

I will demonstrate how Angular 4 event emitters work by example. We are first going to create an application using Angular Cli so you will see how all the pieces fit together in the context of an application. I will then create 1 component and 1 directive. I will add an event emitter to the directive along with a click event listener. When the directive gets clicked the event emitter will call a function in the parent component.

Examples are usually themed around something so I have decided to theme this example around dogs and collars. I have named my component dog and since dogs have collars I have named my directive collar.

Lets Get Started

Create Application :

ng new eventTransmitter  

Create A Component :

ng generate component dog  

Create A Directive :

ng generate directive collar  

Application Entrypoint

The entry point to every Angular CLI generated application is app.module.ts and it is located in the root of the application. That file is called the root module and it loads all of the application modules, directives, components, services ..etc and bootstraps the application. But of course, you should have already known this by now. Notice when I created my component and directive, the cli automatically added the files to the root module.

Collar (Directive)

First, let's program the dog collar.
Collars are usually itchy. We need a way to trigger a collar to start being itchy so the dog knows it is time to scratch. To achieve this functionality, open up the collar directive and add a click hostListener() method. HostListeners attach event listeners to the directive themselves.

Click here to learn more about hostListeners.

Initiate the event emitter on the itch parameter. The event emitter will be used to emit itchies to the dog. When you click on the collar the collar is going to get itchy and the itchiness is emitted to the dog and then the dog will then start scratching.

Your code should look similar to the following :

import { Directive,HostListener,Output,EventEmitter } from '@angular/core';

@Directive({
///appCollar is the collar!
  selector: '[appCollar]'
})
export class CollarDirective {  
/// Event Emitter used to communicate the act of scratching to the dog
  @Output() itch:EventEmitter<any> = new EventEmitter();
/// our click is a representation of a scratch
  @HostListener('onClick') onClick(){
///We are emitting itchies!!
    this.itch.emit('itch itch itch');
  }

  constructor() { }

}

Dog + Collar

We have a few things left before we are done. We need to add the dog to the app and then we need to add the collar on the dog. Open up your app.component.html in the root of the application and add your dog by adding the dog selector.

app.component.html

<h1>  
  {{title}}
</h1>  
<!--- Hello Dog --->  
<app-dog>  
</app-dog>

Now add the collar on the dog. Open up the dog component view and add the collar directive. Make sure to add the word collar between the tags so that you see the collar when you are previewing the application.

dog/dog.component.html

<p>  
  dog works!
</p>  
<div appCollar>  
Collar  
</div>

We are missing a very crucial piece in all this. The dog needs to scratch. Dogs are very literal so you need to tell the dog when the collar gets itchy that it needs to scratch itself. Update the HTML to the following :

dog/dog.component.html

<p>  
  dog works!
</p>  
<div appCollar (itch)='scratch()' >  
  Collar
</div>

Dog (Component)

Perfect ! Now for the last bit. When the dog scratches itself, it will 'woof' letting us know that it is scratching. Create the function of the method 'scratch()' and add an alert to the function. This will notify us that the dog is scratching.

dog/dog.component.ts

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-dog',
  templateUrl: './dog.component.html',
  styleUrls: ['./dog.component.css']
})
export class DogComponent implements OnInit {

  constructor() { }

  ngOnInit() {
  }
/// Alerting us the dog is scratching
  scratch(){
    alert('woof');
  }

}

Great! Our dog now knows that it needs to notify us with a 'woof' each time it is scratching.

Launch the application ng serve and click on the collar. You should see a woof alert! :)

We have successfully propagated an event from a directive to a component.


Feel free to tweet at me if you get lost on any step of the way. I would love to help out. @notMiloBejda