Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / AngularJs

@Input and @Output in Angular

4.00/5 (4 votes)
9 Aug 2017CPOL3 min read 74.2K  
@Input and @Output in Angular

Input and Output are two decorators in Angular responsible for communication between two components.

In this post, we’ll look into how to pass the data to the components using @Input and to get the data back flowing with @Output.

As I mentioned above, @Input and @Output are decorators. So what is a decorator?

Decorator

A decorator is a function that is invoked with @ prefix and followed by class, method, property.

Ex:

@Input()

description: string;

How to Pass Data?

Before we proceed to start coding the Input and Output decorators, let's see how to pass the data to any component.

Think that we have two components parent and child. The selector for the child is say child-comp. Now, if we are in parent component, we’ll just add an attribute to the tag inside of parent’s template.

import { Component } from '@angular/core'

@Component({
  selector: 'my-app',
  template: `
    <child-comp [parentCount]="count"></child-comp>
  `
})

export class App {
  count: number = 10;
}

So, parentCount is the @Input binding for the child element and fullName is the local component’s property, which has data.

@Input

The @Input decorator is for obtaining the data that is passed from a component.

Let’s continue with the above example. Now, we have the data that is coming in from the parent, we’ve to capture the data in the child component using @Input.

All we have to do is add a variable with the name as parentCount and use it to bind the element in the template

Ex: @Input() parentCount: number;

So, the child component will look like this.

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

@Component({
  selector: 'child-comp',
  template: `
    <div>
      {{ parentCount }}
    </div>
  `
})

export class ChildComponent {
  @Input()
  parentCount: number;
}

Do not forget to add our child component to declarations section of the @NgModule.

Aliasing in @Input

We can alias the data that is coming from the component. As in the example above, we could have aliased parentCount like this:

@Input(‘parentCount‘) count: number

Now, we’ll have the data in count variable. Basically, if we have the same variable names that might conflict in the child component, we could alias to a different name.

@Output

So far, we’ve just seen passing data in one-way direction, i.e., from parent component to child component. Now, let’s see how to make a stateful connection between parent and child.

@Output is not just a single thing that can pass data back from child to parent. We have to use EventEmitter to emit the event to the parent so that parent can capture the exposed event and retrieve data.

We’ve to combine @Input decorator to pass the initial data to the child component and get back the updated data using @Output decorator and Event emitter.

Let’s extend the functionality of the above @Input decorator to push back the updated content to parent and display the updated value in the parent component.

//import Output, EventEmitter from angular core
import {Component, Input, Output, EventEmitter} from '@angular/core'

//define the event emitter
 @Output()
 change: EventEmitter<number> = new EventEmitter<number>();
 
 //emit the event with the above change event
this.change.emit(11); //11 will be emitted to the parent

In the above code, we need to import Input, Output, EventEmitter to do the push from child to parent.

We have declared a change event which is of type EventEmitter which pushes a number type of data. Note that change is just an event that we give for the event emitter. It is neither a convention nor a keyword. You can have any custom name as well. I’d encourage you to change the change event name to any custom name in the demo code and make sure it is working.

The event emitter will have emit() method to emit to the parent. Call the last line whenever the parent should be notified of that change.

import {Component} from '@angular/core'

//import the child component
import {ChildComponent} from 'src/child.component'

//add (change) event to the child component selector.
//(change) is the name of the event that is emitted from the child component
@Component({
  selector: 'parent',
  template: `
    <child-comp 
            [parentCount]="count" 
            (change)="updateFromChild($event)"></child-comp>
  `
});

export class ParentComponent {
  count: number = 0; //initial value of count
  
  //This is the event that we subscribe to the child's selector
  //We will receive the data from child in this function
  updateFromChild($event){
    this.count++;
  }
}

So, for the parent, we will just add that EventEmitter’s event to the child component selector here (it is child-comp). As you can see, I’ve added (change) event to the tag and given a method that can receive when the event is emitted.

The $event parameter on the updateFromChild method will have the content that is sent from the component that emitted the event.

Though this is just for passing data back and forth between parent and child, it takes quite a bit of setup to achieve it. But once habituated, this looks pretty simple and easy thing to do in Angular.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)