Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Angular Component Communication, Day 2

DZone's Guide to

Angular Component Communication, Day 2

In Part 2 of this two-part series, we look at a way in which Angular developers can pass data between components in their web applications.

· Web Dev Zone ·
Free Resource

Deploy code to production now. Release to users when ready. Learn how to separate code deployment from user-facing feature releases with LaunchDarkly.

In my last article, we looked at how we can pass data between components using the @Input and @Output directives and using event emitters. Today, let’s see the other two methods, @ViewChild and data services, can be used to pass data between components.

Let’s break up the article into two sections. First, we will look at ViewChild, then move on to data services.

1. Pass Data Using ViewChild

What Is ViewChild?

ViewChild is what allows a component to be injected into another component and gives the available child component the access to the parent component.

In short, to use the properties of the child component, we can use ViewChild. To get this working, let's add two components in the application, namely MasterwithViewChildComponent.ts and ChildwithViewChildComponent.ts.

Below is the ChildwithViewChildComponent.ts file:

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

@Component({
  selector: 'app-childwith-view-child',
  templateUrl: './childwith-view-child.component.html',
  styleUrls: ['./childwith-view-child.component.css']
})

export class ChildwithViewChildComponent implements OnInit {
 counter :;
              IncreaseNumber():void{
  this.counter++;
}
  constructor() { }

  ngOnInit() {

  }

}


When we look at the code snippet, we can see the class has the normal counter property and a method, IncreaseNumber(), which increases the counter by one every time the function is called. Next, let's look at the code snippet for the Master component: 

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

import{ChildwithViewChildComponent} from '../childwith-view-child/childwith-view-child.component'

@Component({
  selector: 'app-masterwith-view-child',
  templateUrl: './masterwith-view-child.component.html',
  styleUrls: ['./masterwith-view-child.component.css']
})

export class MasterwithViewChildComponent implements OnInit {

  @ViewChild(ChildwithViewChildComponent)

private childcomponent : ChildwithViewChildComponent;

Increase():void{
  this.childcomponent.IncreaseNumber();
}

Dicrease():void{
  this.childcomponent.counter--;
}

constructor() { }

  ngOnInit() {

  }

}


Let’s look the things step-by-step:

  1. Import the ViewChild from @angular/core. The @ViewChild decorator is present in Angular Core, so we need to import the package.

  2. The next piece of code, which is a very important snippet, is used to check it:

@ViewChild(ChildwithViewChildComponent)

private childcomponent: ChildwithViewChildComponent;


These lines of code are used to query the child component and inject the same property inside the local object of the child component which is created in the second line.

It also has two functions,  IncreaseNumber() and Decrease()Increase() calls the function which is present in the child component, and Decrease() reduces the counter property of the child component by one. Here, we can modify the master template with following code:

<p>
   <b>@ViewChild with Components..</b>
<br>
<br>
<input type="button" value="Increase" (click)()>
<input type="button" value="Decrease" (click)()>
   <app-childwith-view-child></app-childwith-view-child>
</p>


We have instantiated the child component and the two buttons which will call the Increase() and Decrease() functions in the component and get the output accordingly.

2. Passing Data Using Data Service

Up to this point, we have seen how to work with data sharing between related components; now, let’s see how data is shared across components which are not related. For the components like this, the idea behind having shared data is using a shared service which will sync all the data across the components to which it is referred.

To achieve this, let's add the data service first - this will hold the data that we need for the components. Let's look at the Data.service.ts file:

import { Injectable } from '@angular/core';
import {BehaviorSubject} from 'rxjs'

@Injectable()

export class DataService {
    private messageSource = new BehaviorSubject < string > ("Start");
    .messageSource.asObservable(); 
    constructor() {} 
    changemessage(message: string): void {   
        this.messageSource.next(message); 
    }
}


Above is the code for the DataService class. Before going into the details of this class, let us try to understand some snippets in the code.

Import{Injectable} from ‘@angulr/core’;  

This line, which is the first line in the code, brings the @Injectable decorator into the code. This is used to allow the functionality of the class to be injected and used in the other components or modules.

Import{BehaviorSubject} from ‘rxjs’; 

This is a subject type which can be used to return a special type of the observable which can be used to subscribe to the various types of the messages.

It also gives us the observable from the subject using the Method asobservable()on the behavior subject.

In the above code, we have added the changemessage method which gets the next string from the observable subject and returns the message.

To consume the service in the components, let's add this service as a provider to the Root Module which is the app.module.ts file. Let's add the following snippet in the app module:

providers: [DataService], 

We have added the providers to the app module. Now let's check the components which we want to communicate with each other.

Let's look at the first component:

import { Component, OnInit } from '@angular/core';
import {DataService} from '../data.service'

@Component({
  selector: 'app-first-component',
  templateUrl: './first-component.component.html',
  styleUrls: ['./first-component.component.css']
})


The export class, FirstComponentComponent, implements

OnInit {
    message: string = "";
     constructor(private data: DataService)
    {

    }

    ngOnInit() {          
        this.data.currentmessage.subscribe(message => this.); 
    }
}


In this, we are importing the data service into the component and we can see the constructor of the component is the following: 

constructor(private data:DataService)

{

}


In this, we are adding the object of the data service, which is a singleton object that is created only once. Next, we are looking for any changes in the currentmessage property of the data service which will be assigned to the message property of the class.

Now, let's examine the second component, which has code like below:

import { Component, OnInit } from '@angular/core';
import{DataService} from '../data.service';

@Component({
  selector: 'app-secondcomponent',
  templateUrl: './secondcomponent.component.html',
  styleUrls: ['./secondcomponent.component.css']
})

export class SecondcomponentComponent implements OnInit { 
    childmessage: string = ""
    counter:; constructor(private data: DataService) {} 
    ngOnInit() {   
        this.data.currentmessage.subscribe(Message => this.);
    } 
    newmessage(): void {   
        this.data.changemessage("changing counter from sibling " + this.counter++); 
    }
}


It also has the same way we are subscribing and assigning the value of the currentmessage from the data service to the childmessage property of the class.

Also, we have a new method, newmessage, which calls the data.changeMessage() method which subsequently changes the property of the messageSourceTo run the application, just change the app.component.html file somewhat to look like what I've got below:

<div><strong>Data passing Using Service</strong><br>

First component:: <app-first-component></app-first-component>

<br>

Second Component:: <app-secondcomponent></app-secondcomponent>


To sum up, in order to use a data service to share data between components we should adopt the following steps

  1. Add a DataService class decorated with @Injectable. 

  2. Use the behavior subject from the RxJS BehaviorSubject Subject.

  3. Subscribe to the changing property and assign it to some property in the component.

I hope this helps you get a better grasp on the various ways to handle data flow between components.

Deploy code to production now. Release to users when ready. Learn how to separate code deployment from user-facing feature releases with LaunchDarkly.

Topics:
web dev ,angular ,components ,web application development ,tutorial

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}