Component Communication in Angular: @Input & @Output

Create a seamless flow of data between your components, enabling complex and interactive user experiences.

Welcome! Let's learn how Angular components talk to each other.

/* Starting the journey into component communication... */

Parent to Child: Passing Data with @Input()

The @Input() decorator marks a component property as an "input" channel. It allows a parent component to pass data *down* to its child. In the child, you declare a property with `@Input()`, and in the parent's template, you bind to it using property binding `[ ]`.

Child to Parent: Announcing Events with @Output()

The @Output() decorator creates an "output" channel for a component to send data *up* to its parent. It's almost always used with an `EventEmitter`, which is responsible for firing custom events that the parent can listen for.

EventEmitter: Firing the Event

When the child component needs to communicate something (like a button click), it calls the .emit() method on its `EventEmitter` instance. In the parent's template, you listen for this event using event binding `( )` and execute a method in response.

The Result: A Complete Communication Loop

Combining @Input() and @Output() creates a clear and predictable data flow. Data flows down from parent to child, and events flow up from child to parent. This pattern is fundamental to building robust and maintainable Angular applications.

Practice Zone


Interactive Test 1: Match the Decorator

Match the Angular decorator to its primary function.

Arrastra en el orden correspondiente.


Arrastra las opciones:

@Output() itemAdded = new EventEmitter();
@Input() product: Product;

Completa el código:

Parent to Child______
Child to Parent______
Unlock with Premium

Interactive Test 2: Complete the Child

Rellena los huecos en cada casilla.

// child.component.ts
import { Component, Input, Output, EventEmitter } from '@angular/core';

@Component({ /*...*/ })
export class ChildComponent {
   message: string;
   reply = new EventEmitter<string>();

  sendReply() {
    this.reply.emit('Message received!');
  }
}
Unlock with Premium

Practice Example: Complete the Parent

Complete the parent component to display the message from the child when the event is fired.

Enunciado:

The key is to add the event binding (reply)='handleReply($event)' and the corresponding method in the component class.

* Escribe el código a continuación. Los caracteres correctos se mostrarán en verde y los incorrectos en rojo.

// parent.component.ts @Component({ selector: 'app-parent', template: ` <app-child [message]="parentMessage" (reply)="handleReply($event)"> </app-child> <p>Child replied: {{childsReply}}</p> ` }) export class ParentComponent { parentMessage = "Hello, Child!"; childsReply = ""; handleReply(message: string) { this.childsReply = message; } }

Unlock with Premium

Knowledge Check

To send data from a child to a parent, you use @Output() in combination with what?


Unlock with Premium

Advanced Communication Patterns

While @Input() and @Output() are perfect for direct parent-child relationships, Angular provides other powerful tools for more complex scenarios.


1. Communicating via a Shared Service

When components are not directly related (e.g., they are siblings or in different parts of the component tree), a shared service is the best solution. You create an injectable service that holds the shared state and provide it at a common ancestor level. Components can then inject the service to read or update the shared data.

// data.service.ts
@Injectable({ providedIn: 'root' })
export class DataService {
  private messageSource = new BehaviorSubject('Default message');
  currentMessage = this.messageSource.asObservable();

  changeMessage(message: string) {
    this.messageSource.next(message);
  }
}

2. Parent Accessing Child with @ViewChild

Sometimes a parent component needs to access a property or call a method on its child component directly. You can achieve this using the @ViewChild() decorator to get a direct reference to the child component instance.

// parent.component.ts
import { ViewChild, AfterViewInit } from '@angular/core';
import { ChildComponent } from './child.component';

export class ParentComponent implements AfterViewInit {
  @ViewChild(ChildComponent) private child: ChildComponent;

  ngAfterViewInit() {
    this.child.doSomething(); // Calling a public method on the child
  }
}

Practical Takeaway: Choose the right tool for the job. Use @Input/@Output for simple, direct relationships. For everything else, a shared service provides a more scalable and decoupled architecture.

Component Communication Glossary

Decorator
A special kind of declaration in TypeScript that can be attached to a class, method, or property. Decorators, prefixed with an @ symbol (like @Component or @Input), add metadata to the code that Angular uses to configure behavior.
@Input()
A property decorator that allows data to be passed from a parent component to a child component. It defines an input property on the child that can be bound to in the parent's template.
@Output()
A property decorator that allows a child component to emit custom events up to its parent component. It is typically used with an instance of `EventEmitter`.
EventEmitter
A class from `@angular/core` used to publish events. The child component creates an instance of `EventEmitter` and calls its `.emit()` method to fire an event that the parent can listen for.
Property Binding ([ ])
The syntax used to pass data *into* a component. The square brackets `[]` tell Angular to evaluate the right-hand side as an expression and bind its value to the property on the left.
Event Binding (( ))
The syntax used to listen for events *from* a component. The parentheses `()` tell Angular to execute the right-hand side expression whenever the event on the left is emitted.