How To Pass Data From Child To Parent Component

How To Pass Data From Child To Parent Component

In this article, We will learn how to pass data from a child component to a parent component in Angular. We looked at how to transmit data from the parent component to the child component by changing its input property in the last article. A parent can interact with the child via a local variable or call @ViewChild on the child, or the child can communicate data to the Parent by raising an event. In this essay, we'll look at all of those possibilities.

Pass data from Child to parent component

The parent component can interact with the child component in three different ways.

Parent listens for child event

An EventEmitter Property is exposed by the Child Component. The @Output decorator has been applied to this Property. The event is raised when the Child Component needs to communicate with the parent. The Parent Component is aware of the occurrence and reacts accordingly.

EventEmitter Property

To Raise an event, the component must declare an EventEmmitter Property. The .emit() method can be used to emit the Event.

For Example

countChanged: EventEmitter<number> = new EventEmitter()

Then, as seen below, call the emit method, supplying whatever data you want to transmit.
this.countChanged.emit(this.count);

@Output Decorator

Making Use of the Event The component's Emitter Property allows it to raise an event. However, you must use the @Output decorator to make that event accessible from the parent component.

How to Pass data to parent component using @Output

In the component for children,
  • Declare and instantiate a property of type EventEmitter.
  • Add a @Output Decorator to it.
  • Raise the event and pass it the data you want.

In the component's parent
  • Using Event Binding, connect to the child component and listen for child events.
  • Define the function that will handle the event.

Passing data to parent component Via Events

Let's now create an application to demonstrate this.

We constructed a counter in the parent component in the previous transferring data to child component tutorial. The counter was given an initial value and increment/decrement methods were introduced. The @Input decorator was used in the child Component to tie the count attribute to the parent component. When the parent component's count is modified, the child component is updated and the count is displayed.

In this article, We'll shift the counter to the child component. When the count is increased or lowered, we shall raise an event in the child component. The parent component is then bound to that event, and the count is displayed in the parent component.

Open the child.component.ts and add the following code:
import { Component, Input, Output, EventEmitter  } from '@angular/core';
 
@Component({
    selector: 'child-component',
    template: `<h2>Child Component</h2>
               <button (click)="increment()">Increment</button>
               <button (click)="decrement()">decrement</button>
               current count is {{ count }}
    `
})
export class ChildComponent {
    @Input() count: number;
 
    @Output() countChanged: EventEmitter<number> =   new EventEmitter();
 
    increment() {
        this.count++;
        this.countChanged.emit(this.count);
      }
    decrement() {
        this.count--;
        this.countChanged.emit(this.count);
    }
}

Let's take a closer look at the code.

To begin, we must import output and EventEmitter from @angular/core.
import { Component, Input, Output, EventEmitter } from '@angular/core';

We have two buttons in the inline template: increment and decrement. In addition, we show the current count.
@Component({
    selector: 'child-component',
    template: `<h2>Child Component</h2>
               <button (click)="increment()">Increment</button>
               <button (click)="decrement()">decrement</button>
               current count is {{ count }}
    `
})

Define the countChanged event of type EventEmiiter in the child component. To make the property accessible from the parent component, use the @Output decorator.
@Output() countChanged: EventEmitter<number> = new EventEmitter();


Finally, we use emit to raise the event in increment and decrement procedures.
increment() {
    this.count++;
    this.countChanged.emit(this.count);
  }
decrement() {
    this.count--;
    this.countChanged.emit(this.count);
}

Parent Component

We must listen to the "countChanged" event in the parent component.

Parentheses surround the "countChanged" event. It's then passed to the component class's "countChangedHandler" method. The syntax is comparable to that of Event Binding.
<child-component [count]=ClickCounter (countChanged)="countChangedHandler($event)"></child-component>`

The $event argument is accepted by the countChangedHandler($event) method. The $event property now contains the data connected with the event.

The following is the code for our CountChangedHandler. It just refreshes the clickCounter and logs the number of clicks to the console.
countChangedHandler(count: number) {
  this.ClickCounter = count;
  console.log(count);
}

The following is the whole code:
import { Component} from '@angular/core';
 
@Component({
  selector: 'app-root',
  template: `
        <h1>Welcome to {{title}}!</h1>
        <p> current count is {{ClickCounter}} </p>
        <child-component [count]=Counter (countChanged)="countChangedHandler($event)"></child-component>` ,
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'Component Interaction';
  Counter = 5;
 
  countChangedHandler(count: number) {
    this.Counter = count;
    console.log(count);
  }
}

Now, run the Application. The child raises the event whenever the increment/decrement buttons are pressed. The Parent component is alerted of this, and the counter is updated with the current value.

Parent uses local variable to access the Child in Template

The template reference variable allows the parent template to access the attributes and methods of the child component.

Child Component

Let's make a change to the child component.
import { Component} from '@angular/core';
 
@Component({
    selector: 'child-component',
    template: `<h2>Child Component</h2>
               current count is {{ count }}
    `
})
export class ChildComponent {
    count = 0;
 
     increment() {
        this.count++;
      }
    decrement() {
        this.count--;
    }
}

The input, output, and eventEmiitter have all been removed.

Our component now has a count property with two methods for incrementing and decrementing it.

Parent component

import { Component} from '@angular/core';
 
@Component({
  selector: 'app-root',
  template: `
        <h1>{{title}}!</h1>
        <p> current count is {{child.count}} </p>
        <button (click)="child.increment()">Increment</button>
        <button (click)="child.decrement()">decrement</button>
        <child-component #child></child-component>` ,
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'Parent interacts with child via local variable';
}

On the tag <child-component>, we've added a local variable called #child. The "child" is referred to as the template reference variable, and it now stands for the child component.

When you use #<varibaleName> and attach it to a DOM element, the Template Reference variable is produced. The variable can then be used to refer to the DOM element in your Template.
<child-component #child></child-component>` ,

You may now use the local variable to refer to the child component methods and properties across the template, as seen below.
<p> current count is {{child.count}} </p>
<button (click)="child.increment()">Increment</button>
<button (click)="child.decrement()">decrement</button>

The code above connects the parent component's increment and decrement methods to child components.

The local variable method is basic and straightforward. However, because the parent-child wiring must be done solely within the parent template, it is constrained. The kid is not accessible to the parent component.

If a parent component class instance must read or write child component values or call child component methods, you can't use the local variable strategy.

Parent uses a @ViewChild() to get reference to the Child Component

Another option used by the parent to access the properties and methods of the child component is to inject an instance of the child component into the parent as a @ViewChild.

The name of the component/directive is passed to the @ViewChild decorator as an argument. The material is then used to embellish a home. The component's reference is subsequently injected into the Property by Angular.

For example,

Declare a property of type child in the Parent component. ChildComponent
child: ChildComponent;

Then, using the @ViewChild decorator, give it the name of the component you want to inject.
@ViewChild(ChildComponent) child: ChildComponent;

The reference to the child component is now assigned to the child property when angular generates the child component. Now we're going to update the code from the previous section.

Parent Component

The viewChild Decorator must be imported into the parent component. The kid component must also be imported.
import { Component, ViewChild } from '@angular/core';
import { ChildComponent } from './child.component';

Create a child property that is an instance of the ChildComponent type. As demonstrated below, apply the viewChild Decorator to the child component.
@ViewChild(ChildComponent) child: ChildComponent;

Finally, add increment and decrement methods, which call the child component's methods.
increment() {
  this.child.increment();
}

decrement() {
  this.child.decrement();
}

The parent can now access the child component's attributes and methods. Also, make any necessary adjustments to the app.component.html file.
<h1>{{title}}</h1>
<p> current count is {{child.count}} </p>
<button (click)="increment()">Increment</button>
<button (click)="decrement()">decrement</button>
<child-component></child-component>

The following is the entire app.component.ts file:
import { Component, ViewChild } from '@angular/core';
import { ChildComponent } from './child.component';
 
@Component({
  selector: 'app-root',
  template: `
        <h1>{{title}}</h1>
        <p> current count is {{child.count}} </p>
        <button (click)="increment()">Increment</button>
        <button (click)="decrement()">decrement</button>
        <child-component></child-component>` ,
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'Parent calls an @ViewChild()';
 
  @ViewChild(ChildComponent) child: ChildComponent;
 
  increment() {
    this.child.increment();
  }
 
  decrement() {
    this.child.decrement();
  }
}

Conclusion

In this article, we learned how the parent component can communicate with the child component. The parent component can subscribe to the child component's events. It can access the properties and methods via the Template local variable. The @ViewChild decorator can also be used to inject the child component instance into the parent component. In the next article, we will learn the Component life cycle hooks.

I hope this article helps you and you will like it.👍

If you have any doubt or confusion then free to ask in comment section.

Post a Comment

Previous Post Next Post