Physical Address

304 North Cardinal St.
Dorchester Center, MA 02124

How to Use Input and Output Decorators in Angular: A Step-by-Step Guide

When building complex Angular applications, communication between components is essential.

Angular provides two powerful tools for exchanging data between components: Input and Output decorators.

In this blog post, I’ll walk you through how these decorators work and how to implement them in a real-world scenario.

We’ll also cover creating and handling events with the EventEmitter class.

Let’s dive into the details!

What Are Input and Output Decorators?

In Angular, components can communicate with each other using Input and Output decorators. These decorators make it easy to share data between a parent and child component.

  • The Input decorator allows a parent component to pass data to a child component.
  • The Output decorator allows the child component to send events back to the parent component, typically using EventEmitter.

Why Use Input and Output?

Imagine you’re creating a dynamic form where a user’s input needs to update in real time.

You need a way to pass data between components and ensure that changes in one component reflect in others. The Input and Output decorators give you a clean, maintainable way to do that.

Using the Input Decorator

Let’s start by creating a simple Input component. This component will accept a value from its parent component and display it in the template.

Here’s how you can create a basic TestInputComponent that takes a string as input and displays it.

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

@Component({
  selector: 'app-test-input',
  template: `<h3>Input Value: {{ inputValue }}</h3>`,
})
export class TestInputComponent {
  @Input() inputValue: string = '';
}

In this example:

  • The @Input() decorator is used to define the property inputValue.
  • This property can be passed a value from the parent component.

Embedding the TestInputComponent in AppComponent

Now, let’s add this component to the AppComponent template.

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

@Component({
  selector: 'app-root',
  template: `
    <app-test-input [inputValue]="parentValue"></app-test-input>
  `,
})
export class AppComponent {
  parentValue: string = 'Hello from Parent Component!';
}

Here, the parentValue is passed from the parent component (AppComponent) to the child component (TestInputComponent) using the Input decorator.

Updating Input Dynamically

What if we want the value to update dynamically? Let’s introduce a loop that updates the value over time.

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

@Component({
  selector: 'app-root',
  template: `
    <app-test-input [inputValue]="dynamicValue"></app-test-input>
  `,
})
export class AppComponent {
  dynamicValue: string = 'Initial Value';

  ngOnInit() {
    let counter = 1;
    setInterval(() => {
      this.dynamicValue = `Value ${counter}`;
      counter++;
    }, 1000);
  }
}

Here’s what’s happening:

  • The value of dynamicValue changes every second.
  • The TestInputComponent automatically updates as dynamicValue changes, showing the updated values in the browser.

Using the Output Decorator

Now that we’ve covered passing data into a component using Input, let’s explore how to emit events from a component using the Output decorator.

We’ll create a TestOutputComponent that contains a button. When the button is clicked, the component will emit an event to the parent component.

Setting Up the Output

First, define the child component with an Output event emitter.

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

@Component({
  selector: 'app-test-output',
  template: `<button (click)="emitEvent()">Click Me!</button>`,
})
export class TestOutputComponent {
  @Output() myEvent = new EventEmitter<string>();

  emitEvent() {
    this.myEvent.emit('Event Emitted!');
  }
}

In this code:

  • The @Output() decorator is used to define an event emitter named myEvent.
  • The emitEvent() function emits a string ('Event Emitted!') when the button is clicked.

Handling the Output Event in the Parent Component

Now, we’ll handle the emitted event in the parent component.

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

@Component({
  selector: 'app-root',
  template: `
    <app-test-output (myEvent)="handleEvent($event)"></app-test-output>
  `,
})
export class AppComponent {
  handleEvent(eventData: string) {
    console.log('Received Event:', eventData);
  }
}
  • We bind the myEvent output from the child component to a method in the parent component called handleEvent.
  • When the button is clicked, the event data ('Event Emitted!') is logged in the console.

Testing the Output Event

To see this in action:

  1. Add the TestOutputComponent to the parent template.
  2. Open the browser and click the button.
  3. Check the console log to see the event being emitted.

Complete Example Code

Here’s the full code for both components:

TestInputComponent (Child Component)

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

@Component({
  selector: 'app-test-input',
  template: `<h3>Input Value: {{ inputValue }}</h3>`,
})
export class TestInputComponent {
  @Input() inputValue: string = '';
}

TestOutputComponent (Child Component)

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

@Component({
  selector: 'app-test-output',
  template: `<button (click)="emitEvent()">Click Me!</button>`,
})
export class TestOutputComponent {
  @Output() myEvent = new EventEmitter<string>();

  emitEvent() {
    this.myEvent.emit('Event Emitted!');
  }
}

AppComponent (Parent Component)

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

@Component({
  selector: 'app-root',
  template: `
    <app-test-input [inputValue]="dynamicValue"></app-test-input>
    <app-test-output (myEvent)="handleEvent($event)"></app-test-output>
  `,
})
export class AppComponent {
  dynamicValue: string = 'Initial Value';

  ngOnInit() {
    let counter = 1;
    setInterval(() => {
      this.dynamicValue = `Value ${counter}`;
      counter++;
    }, 1000);
  }

  handleEvent(eventData: string) {
    console.log('Received Event:', eventData);
  }
}

Conclusion

Using Input and Output decorators in Angular helps you manage data flow between components, making your application easier to scale and maintain.

You can pass values into a component with Input, and emit events using Output with EventEmitter. This communication mechanism is key to building modular, reusable components in Angular.

Feel free to experiment with this setup by passing different data types, handling multiple events, or even chaining outputs from different components. Happy coding!