Kshlerin WebStudio πŸš€

How to call another components function in angular2

September 19, 2026

πŸ“‚ Categories: Programming
How to call another components function in angular2

Angular, a robust framework for building dynamic web applications, often requires components to interact with each other. One common scenario is needing to call another component’s function in Angular. This interaction can be achieved in several ways, each with its own advantages and use cases. Whether you’re dealing with parent-child component relationships, sibling components, or completely unrelated components, understanding the proper techniques is crucial for building maintainable and scalable Angular applications. This article delves into the various methods to facilitate this communication, providing you with practical examples and best practices to streamline your Angular development process. Mastering these techniques allows for better component reusability and a more modular application architecture, which ultimately translates to more efficient development and easier maintenance.

Understanding Component Communication in Angular

Component communication is a cornerstone of Angular development. Effective communication ensures that different parts of your application can work together seamlessly. Angular provides several mechanisms to facilitate this, including Input and Output bindings, services, and the use of a shared state management library like NgRx or Akita. Choosing the right method depends on the relationship between the components and the overall architecture of your application. For instance, parent-child communication is often best handled with Input and Output bindings, while communication between unrelated components might be better suited for a service. Understanding these nuances is key to building robust and maintainable Angular applications.

Input and Output bindings allow for direct communication between parent and child components. The parent component can pass data down to the child component using Input bindings, and the child component can emit events back to the parent using Output bindings. This creates a clear and well-defined communication channel. Services, on the other hand, provide a more loosely coupled approach. A service can be injected into multiple components, allowing them to share data and functionality. This is particularly useful for communication between components that are not directly related in the component tree. “Effective component communication is critical for building maintainable and scalable Angular applications,” says John Papa, a renowned Angular expert (JohnPapa.net).

State management libraries like NgRx provide a centralized store for your application’s state. This can be particularly useful for complex applications where multiple components need to access and modify the same data. By using a state management library, you can ensure that your application’s state is consistent and predictable. These libraries often involve more boilerplate code but can significantly improve the maintainability of larger applications. Carefully consider the complexity of your application when choosing a communication method. Simpler applications might not need the overhead of a state management library, while larger applications can benefit greatly from its structure and predictability.

Using @Input and @Output Decorators for Parent-Child Communication

The @Input and @Output decorators are fundamental for managing communication between parent and child components in Angular. These decorators allow you to define properties in the child component that can receive data from the parent, and events that the child can emit back to the parent. This approach creates a clear and structured communication channel, making it easy to understand the flow of data between related components. Proper use of @Input and @Output can significantly improve the readability and maintainability of your Angular code.

To use @Input, you decorate a property in the child component. The parent component can then bind to this property using property binding syntax ([]). Any changes made to the property in the parent component will be reflected in the child component. For example:

// Child Component import { Component, Input } from '@angular/core'; @Component({ selector: 'app-child', template: '<p>Message from parent: {{ message }}</p>' }) export class ChildComponent { @Input() message: string; } // Parent Component import { Component } from '@angular/core'; @Component({ selector: 'app-parent', template: '<app-child [message]="parentMessage"></app-child>' }) export class ParentComponent { parentMessage = 'Hello from parent!'; } 

To use @Output, you decorate a property in the child component with the EventEmitter class. The child component can then emit events using the emit() method. The parent component can bind to this event using event binding syntax (()). When the child component emits the event, the parent component’s event handler will be called. For example:

// Child Component import { Component, Output, EventEmitter } from '@angular/core'; @Component({ selector: 'app-child', template: '<button (click)="sendMessage()">Send Message</button>' }) export class ChildComponent { @Output() messageEvent = new EventEmitter<string>(); sendMessage() { this.messageEvent.emit('Hello from child!'); } } // Parent Component import { Component } from '@angular/core'; @Component({ selector: 'app-parent', template: '<app-child (messageEvent)="receiveMessage($event)"></app-child>' }) export class ParentComponent { receiveMessage(message: string) { console.log(message); } } 

Using @Input and @Output is a clean and efficient way to manage communication between parent and child components. It promotes a clear separation of concerns and makes your code easier to understand and maintain. This method is especially effective when the data flow is directly between parent and child, avoiding the complexities of more global state management solutions for simple interactions. This directness enhances performance and reduces the chances of unintended side effects in larger applications.

Leveraging Services for Component Communication

Services in Angular provide a powerful mechanism for communication between components, especially those that are not directly related as parent and child. A service acts as a singleton, meaning only one instance of the service is created and shared across the application. This makes services ideal for sharing data and functionality between different parts of your application. By injecting a service into multiple components, you can enable them to communicate with each other without needing to pass data directly between them. This approach promotes loose coupling and makes your code more modular and testable.

To use a service for component communication, you first need to create the service using the Angular CLI. For example:

ng generate service data 

This will create a data.service.ts file. In this file, you can define the data and methods that you want to share between components. For example:

// data.service.ts import { Injectable } from '@angular/core'; import { Subject } from 'rxjs'; @Injectable({ providedIn: 'root' }) export class DataService { private messageSource = new Subject<string>(); message$ = this.messageSource.asObservable(); sendMessage(message: string) { this.messageSource.next(message); } } 

In this example, we’re using a Subject from RxJS to create an observable that components can subscribe to in order to receive messages. The sendMessage() method is used to send messages to the observable. Now, you can inject this service into your components and use it to send and receive messages:

// Component 1 import { Component, OnInit } from '@angular/core'; import { DataService } from './data.service'; @Component({ selector: 'app-component1', template: '<button (click)="sendMessage()">Send Message</button>' }) export class Component1 implements OnInit { constructor(private dataService: DataService) {} ngOnInit() {} sendMessage() { this.dataService.sendMessage('Hello from Component 1!'); } } // Component 2 import { Component, OnInit } from '@angular/core'; import { DataService } from './data.service'; @Component({ selector: 'app-component2', template: '<p>Message: {{ message }}</p>' }) export class Component2 implements OnInit { message: string; constructor(private dataService: DataService) {} ngOnInit() { this.dataService.message$.subscribe(message => { this.message = message; }); } } 

This example demonstrates how two unrelated components can communicate using a service. Component 1 sends a message using the DataService, and Component 2 subscribes to the message$ observable to receive the message. Services are a versatile tool for managing communication in Question & Answer :

I have two components as follows and I want to call a function from another component. Both components are included in the third parent component using directive.

Component 1:

@component( selector:'com1' ) export class com1{ function1(){...} } 

Component 2:

@component( selector:'com2' ) export class com2{ function2(){... // i want to call function 1 from com1 here } } 

I’ve tried using @input and @output but I don’t understand exactly how to use it and how to call that function, can anyone help?

First, what you need to understand the relationships between components. Then you can choose the right method of communication. I will try to explain all the methods that I know and use in my practice for communication between components.

What kinds of relationships between components can there be?

1. Parent > Child

enter image description here

Sharing Data via Input

This is probably the most common method of sharing data. It works by using the @Input() decorator to allow data to be passed via the template.

parent.component.ts

import { Component } from '@angular/core'; @Component({ selector: 'parent-component', template: ` <child-component [childProperty]="parentProperty"></child-component> `, styleUrls: ['./parent.component.css'] }) export class ParentComponent{ parentProperty = "I come from parent" constructor() { } } 

child.component.ts

import { Component, Input } from '@angular/core'; @Component({ selector: 'child-component', template: ` Hi {{ childProperty }} `, styleUrls: ['./child.component.css'] }) export class ChildComponent { @Input() childProperty: string; constructor() { } } 

This is a very simple method. It is easy to use. We can also catch changes to the data in the child component using ngOnChanges.

But do not forget that if we use an object as data and change the parameters of this object, the reference to it will not change. Therefore, if we want to receive a modified object in a child component, it must be immutable.

2. Child > Parent

enter image description here

Sharing Data via ViewChild

ViewChild allows one component to be injected into another, giving the parent access to its attributes and functions. One caveat, however, is that child won’t be available until after the view has been initialized. This means we need to implement the AfterViewInit lifecycle hook to receive the data from the child.

parent.component.ts

import { Component, ViewChild, AfterViewInit } from '@angular/core'; import { ChildComponent } from "../child/child.component"; @Component({ selector: 'parent-component', template: ` Message: {{ message }} <child-compnent></child-compnent> `, styleUrls: ['./parent.component.css'] }) export class ParentComponent implements AfterViewInit { @ViewChild(ChildComponent) child; constructor() { } message:string; ngAfterViewInit() { this.message = this.child.message } } 

child.component.ts

import { Component} from '@angular/core'; @Component({ selector: 'child-component', template: ` `, styleUrls: ['./child.component.css'] }) export class ChildComponent { message = 'Hello!'; constructor() { } } 

Sharing Data via Output() and EventEmitter

Another way to share data is to emit data from the child, which can be listed by the parent. This approach is ideal when you want to share data changes that occur on things like button clicks, form entries, and other user events.

parent.component.ts

import { Component } from '@angular/core'; @Component({ selector: 'parent-component', template: ` Message: {{message}} <child-component (messageEvent)="receiveMessage($event)"></child-component> `, styleUrls: ['./parent.component.css'] }) export class ParentComponent { constructor() { } message:string; receiveMessage($event) { this.message = $event } } 

child.component.ts

import { Component, Output, EventEmitter } from '@angular/core'; @Component({ selector: 'child-component', template: ` <button (click)="sendMessage()">Send Message</button> `, styleUrls: ['./child.component.css'] }) export class ChildComponent { message: string = "Hello!" @Output() messageEvent = new EventEmitter<string>(); constructor() { } sendMessage() { this.messageEvent.emit(this.message) } } 

3. Siblings

enter image description here

Child > Parent > Child

I try to explain other ways to communicate between siblings below. But you could already understand one of the ways of understanding the above methods.

parent.component.ts

import { Component } from '@angular/core'; @Component({ selector: 'parent-component', template: ` Message: {{message}} <child-one-component (messageEvent)="receiveMessage($event)"></child1-component> <child-two-component [childMessage]="message"></child2-component> `, styleUrls: ['./parent.component.css'] }) export class ParentComponent { constructor() { } message: string; receiveMessage($event) { this.message = $event } } 

child-one.component.ts

import { Component, Output, EventEmitter } from '@angular/core'; @Component({ selector: 'child-one-component', template: ` <button (click)="sendMessage()">Send Message</button> `, styleUrls: ['./child-one.component.css'] }) export class ChildOneComponent { message: string = "Hello!" @Output() messageEvent = new EventEmitter<string>(); constructor() { } sendMessage() { this.messageEvent.emit(this.message) } } 

child-two.component.ts

import { Component, Input } from '@angular/core'; @Component({ selector: 'child-two-component', template: ` {{ message }} `, styleUrls: ['./child-two.component.css'] }) export class ChildTwoComponent { @Input() childMessage: string; constructor() { } } 

4. Unrelated Components

enter image description here

All the methods that I have described below can be used for all the above options for the relationship between the components. But each has its own advantages and disadvantages.

Sharing Data with a Service

When passing data between components that lack a direct connection, such as siblings, grandchildren, etc, you should be using a shared service. When you have data that should always be in sync, I find the RxJS BehaviorSubject very useful in this situation.

data.service.ts

import { Injectable } from '@angular/core'; import { BehaviorSubject } from 'rxjs'; @Injectable() export class DataService { private messageSource = new BehaviorSubject('default message'); currentMessage = this.messageSource.asObservable(); constructor() { } changeMessage(message: string) { this.messageSource.next(message) } } 

first.component.ts

import { Component, OnInit } from '@angular/core'; import { DataService } from "../data.service"; @Component({ selector: 'first-componennt', template: ` {{message}} `, styleUrls: ['./first.component.css'] }) export class FirstComponent implements OnInit { message:string; constructor(private data: DataService) { // The approach in Angular 6 is to declare in constructor this.data.currentMessage.subscribe(message => this.message = message); } ngOnInit() { this.data.currentMessage.subscribe(message => this.message = message) } } 

second.component.ts

import { Component, OnInit } from '@angular/core'; import { DataService } from "../data.service"; @Component({ selector: 'second-component', template: ` {{message}} <button (click)="newMessage()">New Message</button> `, styleUrls: ['./second.component.css'] }) export class SecondComponent implements OnInit { message:string; constructor(private data: DataService) { } ngOnInit() { this.data.currentMessage.subscribe(message => this.message = message) } newMessage() { this.data.changeMessage("Hello from Second Component") } } 

Sharing Data with a Route

Sometimes you need not only pass simple data between component but save some state of the page. For example, we want to save some filter in the online market and then copy this link and send to a friend. And we expect it to open the page in the same state as us. The first, and probably the quickest, way to do this would be to use query parameters.

Query parameters look more along the lines of /people?id= where id can equal anything and you can have as many parameters as you want. The query parameters would be separated by the ampersand character.

When working with query parameters, you don’t need to define them in your routes file, and they can be named parameters. For example, take the following code:

page1.component.ts

import {Component} from "@angular/core"; import {Router, NavigationExtras} from "@angular/router"; @Component({ selector: "page1", template: ` <button (click)="onTap()">Navigate to page2</button> `, }) export class Page1Component { public constructor(private router: Router) { } public onTap() { let navigationExtras: NavigationExtras = { queryParams: { "firstname": "Nic", "lastname": "Raboy" } }; this.router.navigate(["page2"], navigationExtras); } } 

In the receiving page, you would receive these query parameters like the following:

page2.component.ts

import {Component} from "@angular/core"; import {ActivatedRoute} from "@angular/router"; @Component({ selector: "page2", template: ` <span>{{firstname}}</span> <span>{{lastname}}</span> `, }) export class Page2Component { firstname: string; lastname: string; public constructor(private route: ActivatedRoute) { this.route.queryParams.subscribe(params => { this.firstname = params["firstname"]; this.lastname = params["lastname"]; }); } } 

NgRx

The last way, which is more complicated but more powerful, is to use NgRx. This library is not for data sharing; it is a powerful state management library. I can’t in a short example explain how to use it, but you can go to the official site and read the documentation about it.

To me, NgRx Store solves multiple issues. For example, when you have to deal with observables and when responsibility for some observable data is shared between different components, the store actions and reducer ensure that data modifications will always be performed “the right way”.

It also provides a reliable solution for HTTP requests caching. You will be able to store the requests and their responses so that you can verify that the request you’re making does not have a stored response yet.

You can read about NgRx and understand whether you need it in your app or not:

Finally, I want to say that before choosing some of the methods for sharing data you need to understand how this data will be used in the future. I mean maybe just now you can use just an @Input decorator for sharing a username and surname. Then you will add a new component or new module (for example, an admin panel) which needs more information about the user. This means that may be a better way to use a service for user data or some other way to share data. You need to think about it more before you start implementing data sharing.