Angular Pass Data Between Components Tutorial | @Input, @Output & ViewChild

Angular Pass Data Between Components Tutorial | @Input, @Output & ViewChild

AI Reading

Quick summary of this article

Angular components are reusable building blocks, and sharing data between them is a common need. This tutorial covers the three primary methods for component communication: using @Input() to pass data from a parent to a child, using @Output() with EventEmitter to send data from a child to a parent, and using @ViewChild() to let a parent directly access a child component's properties or methods.

  • Parent to Child with @Input(): The parent component binds a value to a property on the child component using square brackets (e.g., [message]="data"), and the child declares that property with the @Input() decorator to receive it.
  • Child to Parent with @Output(): The child component defines an @Output() property that is an EventEmitter. It emits data (e.g., this.event.emit(data)), and the parent listens for this custom event using parentheses (e.g., (event)="handler($event)") to receive the payload.
  • Parent Accessing Child with @ViewChild(): The parent uses the @ViewChild() decorator to get a reference to a child component. This allows the parent to call public methods or read public variables directly from the child.
  • Lifecycle Hook for ViewChild: When using @ViewChild(), the child component's view is only available after the parent's view is initialized. Therefore, you must access the child's properties or methods inside the ngAfterViewInit() lifecycle hook.
  • Choosing the Right Method: Use @Input() for one-way data flow down to a child, @Output() for events flowing up to a parent, and @ViewChild() when a parent needs imperative control over a child's specific functionality.

🚀 Angular Pass Data Tutorial: Parent to Child, Child to Parent & ViewChild

In Angular, components are used to divide an application into small reusable parts. Many times, we need to pass data from one component to another component. Angular provides different ways to share data between components.

In this tutorial, we will learn the 3 most important ways to pass data in Angular:

  • Parent Component to Child Component using @Input()
  • Child Component to Parent Component using @Output() and EventEmitter
  • Access Child Component from Parent using @ViewChild()

1. 📌 Parent to Child Data Passing using @Input()

When we want to send data from a parent component to a child component, we use @Input().

✅ Example Structure

src/app/
│
├── parent/
│   ├── parent.component.ts
│   └── parent.component.html
│
└── child/
    ├── child.component.ts
    └── child.component.html

📄 parent.component.ts

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

@Component({
  selector: 'app-parent',
  templateUrl: './parent.component.html'
})
export class ParentComponent {

  parentMessage: string = 'Hello Child, this message is coming from Parent Component';

}

📄 parent.component.html

<h2>Parent Component</h2>

<app-child [messageFromParent]="parentMessage"></app-child>

📄 child.component.ts

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

@Component({
  selector: 'app-child',
  templateUrl: './child.component.html'
})
export class ChildComponent {

  @Input() messageFromParent: string = '';

}

📄 child.component.html

<h3>Child Component</h3>

<p>{{ messageFromParent }}</p>

🧠 Explanation

  • @Input() is used inside the child component.
  • The parent sends data using property binding.
  • [messageFromParent]=”parentMessage” means parentMessage value is passed to the child.

2. 📌 Child to Parent Data Passing using @Output()

When we want to send data from a child component to a parent component, we use @Output() with EventEmitter.

📄 child.component.ts

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

@Component({
  selector: 'app-child',
  templateUrl: './child.component.html'
})
export class ChildComponent {

  @Output() sendDataToParent = new EventEmitter<string>();

  sendMessage() {
    this.sendDataToParent.emit('Hello Parent, this message is coming from Child Component');
  }

}

📄 child.component.html

<h3>Child Component</h3>

<button (click)="sendMessage()">Send Message to Parent</button>

📄 parent.component.ts

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

@Component({
  selector: 'app-parent',
  templateUrl: './parent.component.html'
})
export class ParentComponent {

  childMessage: string = '';

  receiveMessage(data: string) {
    this.childMessage = data;
  }

}

📄 parent.component.html

<h2>Parent Component</h2>

<app-child (sendDataToParent)="receiveMessage($event)"></app-child>

<p>Message from Child: {{ childMessage }}</p>

🧠 Explanation

  • @Output() creates a custom event.
  • EventEmitter emits data from child to parent.
  • The parent listens using event binding.
  • $event receives the data sent from the child component.

3. 📌 Parent Access Child using @ViewChild()

Sometimes, the parent component needs to directly access a child component method or variable. For this, Angular provides @ViewChild().

📄 child.component.ts

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

@Component({
  selector: 'app-child',
  templateUrl: './child.component.html'
})
export class ChildComponent {

  childName: string = 'Angular Child Component';

  showChildMessage() {
    return 'This method is called from Child Component';
  }

}

📄 child.component.html

<h3>Child Component</h3>

<p>Child component is working!</p>

📄 parent.component.ts

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

@Component({
  selector: 'app-parent',
  templateUrl: './parent.component.html'
})
export class ParentComponent implements AfterViewInit {

  @ViewChild(ChildComponent) childComponent!: ChildComponent;

  childData: string = '';
  childMethodMessage: string = '';

  ngAfterViewInit() {
    this.childData = this.childComponent.childName;
    this.childMethodMessage = this.childComponent.showChildMessage();
  }

}

📄 parent.component.html

<h2>Parent Component</h2>

<app-child></app-child>

<p>Child Variable Value: {{ childData }}</p>

<p>Child Method Message: {{ childMethodMessage }}</p>

🧠 Explanation

  • @ViewChild() allows parent to access child component.
  • It can access child variables and methods.
  • ngAfterViewInit() is used because the child view is available after the view is initialized.

⚡ Complete Comparison Table

Method Direction Decorator Used Best Use Case
Parent to Child Parent → Child @Input() Send data like title, user info, product details
Child to Parent Child → Parent @Output() Send button click, form data, selected value
ViewChild Parent accesses Child @ViewChild() Call child method or access child property

🎯 Real-Life Example

Suppose we are building a student management application.

  • Parent component has student data.
  • Child component displays student details.
  • Child component sends selected student back to parent.
  • Parent can also call child methods using ViewChild.

📄 parent.component.ts

import { Component, ViewChild, AfterViewInit } from '@angular/core';
import { StudentChildComponent } from '../student-child/student-child.component';

@Component({
  selector: 'app-student-parent',
  templateUrl: './student-parent.component.html'
})
export class StudentParentComponent implements AfterViewInit {

  studentName: string = 'Rahul Kumar';
  selectedStudent: string = '';

  @ViewChild(StudentChildComponent) studentChild!: StudentChildComponent;

  ngAfterViewInit() {
    console.log(this.studentChild.childInfo());
  }

  getStudentFromChild(student: string) {
    this.selectedStudent = student;
  }

}

📄 parent.component.html

<h2>Student Parent Component</h2>

<app-student-child 
  [student]="studentName"
  (studentSelected)="getStudentFromChild($event)">
</app-student-child>

<p>Selected Student: {{ selectedStudent }}</p>

📄 student-child.component.ts

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

@Component({
  selector: 'app-student-child',
  templateUrl: './student-child.component.html'
})
export class StudentChildComponent {

  @Input() student: string = '';

  @Output() studentSelected = new EventEmitter<string>();

  selectStudent() {
    this.studentSelected.emit(this.student);
  }

  childInfo() {
    return 'Student Child Component Loaded Successfully';
  }

}

📄 student-child.component.html

<h3>Student Child Component</h3>

<p>Student Name: {{ student }}</p>

<button (click)="selectStudent()">Select Student</button>

🧪 Practical Assignment

✅ Assignment Task

Create an Angular application with two components:

  • ParentComponent
  • ChildComponent

You have to implement all 3 ways of passing data:

  1. Send course name from parent to child using @Input()
  2. Send selected course back from child to parent using @Output()
  3. Call child component method from parent using @ViewChild()

📋 Expected Output

Parent Component
Course sent to child: Angular Full Course

Child Component
Course Name: Angular Full Course

Button: Send Course to Parent

Parent receives:
Selected Course: Angular Full Course

ViewChild Message:
Child method called successfully

💡 Important Notes

  • Use @Input() when parent sends data to child.
  • Use @Output() when child sends data to parent.
  • Use @ViewChild() when parent needs direct access to child component.
  • Use ngAfterViewInit() with ViewChild because child view is available after initialization.

✅ Final Summary

Question Answer
How to pass data from parent to child? Using @Input()
How to pass data from child to parent? Using @Output() and EventEmitter
How to access child method from parent? Using @ViewChild()
Which lifecycle hook is used with ViewChild? ngAfterViewInit()

Leave a Reply

Your email address will not be published. Required fields are marked *