How to Pass Data Between Components in Angular

When working with Angular applications, you’ll often need to pass data between components. Whether it’s sending information from a parent to a child or vice versa, Angular provides powerful and simple mechanisms to achieve this. In this blog, we’ll explore these mechanisms with practical examples.


Scenario

Let’s assume we have an application where a Parent Component displays a list of items, and a Child Component is responsible for rendering the details of the selected item. Here’s how to pass data effectively between these components.


Passing Data from Parent to Child Using @Input

The @Input decorator allows the parent component to pass data to the child component.

Steps to Implement:

  • Create Parent and Child Components: Generate the components using Angular CLI:
ng generate component parent
ng generate component child
  • Modify Child Component (child.component.ts): Use the @Input decorator to define a property that will receive data from the parent.
import { Component, Input } from '@angular/core';

@Component({
  selector: 'app-child',
  template: `<p>Selected Item: {{ selectedItem }}</p>`,
})
export class ChildComponent {
  @Input() selectedItem!: string; // Data passed from parent
}
  • Modify Parent Component (parent.component.ts): Pass data to the child component using property binding.
import { Component } from '@angular/core';

@Component({
  selector: 'app-parent',
  template: `
    <div>
      <h3>Items:</h3>
      <ul>
        <li *ngFor="let item of items" (click)="selectItem(item)">
          {{ item }}
        </li>
      </ul>
      <app-child [selectedItem]="currentItem"></app-child>
    </div>
  `,
})
export class ParentComponent {
  items = ['Item 1', 'Item 2', 'Item 3'];
  currentItem = '';

  selectItem(item: string) {
    this.currentItem = item;
  }
}
  • Output:
    • Clicking on an item in the parent list will update the currentItem, which is passed to the child component.
    • The child component will display the selected item.

Passing Data from Child to Parent Using @Output and EventEmitter

When the child component needs to send data back to the parent, Angular provides the @Output decorator along with EventEmitter.

Steps to Implement:

  • Modify Child Component (child.component.ts): Add an event emitter to emit data to the parent.
import { Component, EventEmitter, Output } from '@angular/core';

@Component({
  selector: 'app-child',
  template: `
    <button (click)="notifyParent()">Notify Parent</button>
  `,
})
export class ChildComponent {
  @Output() notify = new EventEmitter<string>();

  notifyParent() {
    this.notify.emit('Data from Child');
  }
}
  • Modify Parent Component (parent.component.ts): Listen for the child’s event using event binding (eventName) syntax.
import { Component } from '@angular/core';

@Component({
  selector: 'app-parent',
  template: `
    <app-child (notify)="onChildNotify($event)"></app-child>
    <p>Message from Child: {{ messageFromChild }}</p>
  `,
})
export class ParentComponent {
  messageFromChild = '';

  onChildNotify(message: string) {
    this.messageFromChild = message;
  }
}
  • Output:
    • Clicking the button in the child component emits an event.
    • The parent component listens for the event and updates its view with the received data.

Two-Way Data Binding Between Components

For scenarios where you need two-way communication, you can combine @Input and @Output.

Steps to Implement:

  • Child Component (child.component.ts): Add both @Input and @Output with EventEmitter.
import { Component, EventEmitter, Input, Output } from '@angular/core';

@Component({
  selector: 'app-child',
  template: `
    <input [value]="childValue" (input)="updateValue($event.target.value)" />
  `,
})
export class ChildComponent {
  @Input() childValue!: string;
  @Output() childValueChange = new EventEmitter<string>();

  updateValue(newValue: string) {
    this.childValueChange.emit(newValue);
  }
}
  • Parent Component (parent.component.ts): Use the [(value)] syntax to enable two-way data binding.
import { Component } from '@angular/core';

@Component({
  selector: 'app-parent',
  template: `
    <app-child [(childValue)]="parentValue"></app-child>
    <p>Value in Parent: {{ parentValue }}</p>
  `,
})
export class ParentComponent {
  parentValue = 'Initial Value';
}
  • Output:
    • Modifying the input field in the child component updates the value in the parent component, and vice versa.

Conclusion

Passing data between components is a common requirement in Angular applications. By using @Input, @Output, and combining them for two-way data binding, you can achieve seamless communication between components.

These approaches not only make your components modular and reusable but also maintain a clean and maintainable codebase. Start applying these techniques in your Angular apps today!

Happy Coding!

Leave a comment