How to call a function from another component in Angular 17?
Are you working on an Angular project and need to call a function from a different component? This is a common task in Angular development, and there are a few different ways to achieve it. In this blog post, we'll explore two popular methods: using child components and utilizing services.
Method 1: Using Child Components
This method is simple and straightforward, but it requires the target component to be a direct child of the component calling the function.
1- Create a Child Component: Start by generating a new component using the Angular CLI. For example, we'll create a child component called "child".
ng generate component child
1ng generate component child
2- Define the Function in the Child Component: Within the child component's TypeScript file, define the function you want to call.
import { Component } from '@angular/core'; @Component({ selector: 'app-child', standalone:true, templateUrl: './child.component.html', styleUrls: ['./child.component.scss'], imports: [CommonModule, RouterOutlet], }) export class ChildComponent { headingVisible = false; showHeading(): void { // Your logic here this.headingVisible = true; } }
1import { Component } from '@angular/core';
2
3@Component({
4 selector: 'app-child',
5 standalone:true,
6 templateUrl: './child.component.html',
7 styleUrls: ['./child.component.scss'],
8 imports: [CommonModule, RouterOutlet],
9})
10export class ChildComponent {
11 headingVisible = false;
12 showHeading(): void {
13 // Your logic here
14 this.headingVisible = true;
15 }
16}
3- Import the Child Component: In the parent component’s TypeScript file, import the child component and add into the imports array of child.component.ts
import { Component } from '@angular/core'; import { ChildComponent } from './child/child.component'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.scss'], imports: [CommonModule, RouterOutlet, ChildComponent], }) export class AppComponent { }
1import { Component } from '@angular/core';
2import { ChildComponent } from './child/child.component';
3
4@Component({
5 selector: 'app-root',
6 templateUrl: './app.component.html',
7 styleUrls: ['./app.component.scss'],
8 imports: [CommonModule, RouterOutlet, ChildComponent],
9
10})
11export class AppComponent {
12
13}
14
4- Use the Child Component in the Template: Add the child component to the parent component's HTML template.
<app-child></app-child>
1<app-child></app-child>
Now, you can access the function defined in the child component using the @ViewChild
decorator in the parent component's TypeScript file. In following code we added @ViewChild
decorator and passed it the ChildComponent class and defined the property child on it of type ChildComponent
.
import { Component, ViewChild } from '@angular/core'; import { ChildComponent } from './child/child.component'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.scss'] }) export class AppComponent { @ViewChild(ChildComponent) child: ChildComponent; }
1import { Component, ViewChild } from '@angular/core';
2import { ChildComponent } from './child/child.component';
3
4@Component({
5 selector: 'app-root',
6 templateUrl: './app.component.html',
7 styleUrls: ['./app.component.scss']
8})
9export class AppComponent {
10 @ViewChild(ChildComponent) child: ChildComponent;
11}
12
5- Calling the function of child component from app component Template: In the component's template file, create a button, register the click event and call the showHeading
function from the child component by using child
property.
<app-child></app-child> <button (click)="child.showHeading()">Show Child Heading<button>
1<app-child></app-child>
2<button (click)="child.showHeading()">Show Child Heading<button>
Before Button Click:
After button click:
Method 2: Using Services
This method is more flexible as it allows you to call functions between components that are not directly related.
1- Create a Service: Generate a service using the Angular CLI.
ng generate service general
1ng generate service general
2- Define the Function in the Service: In the service's TypeScript file, we added a property onButtonClick
and assigned it an instance of rxjs' Subject
class with data type of string.
import { Injectable } from '@angular/core'; import { Subject } from 'rxjs'; @Injectable({ providedIn: 'root' }) export class GeneralService { onButtonClick = new Subject<string>(); }
1import { Injectable } from '@angular/core';
2import { Subject } from 'rxjs';
3
4@Injectable({
5 providedIn: 'root'
6})
7export class GeneralService {
8 onButtonClick = new Subject<string>();
9}
10
3- Generate two components: Generate two components, sidebar
and content
, that would be sibling in app.component.html later.
ng generate c sidebar && ng g c content
1ng generate c sidebar && ng g c content
4- Inject the Service: In both the components, sidebar.component.ts
, content.component.ts
, that need to access the function, inject the service using the inject
function. Make sure to import the inject
function from @angular/core
// In sidebar.component.ts import { Component, OnInit, inject } from '@angular/core'; import { GeneralService } from '../general.service'; @Component({ selector: 'app-sidebar', templateUrl: './sidebar.component.html', styleUrls: ['./sidebar.component.scss'] }) export class SidebarComponent { generalService = inject(GeneralService) }
1// In sidebar.component.ts
2import { Component, OnInit, inject } from '@angular/core';
3import { GeneralService } from '../general.service';
4
5@Component({
6 selector: 'app-sidebar',
7 templateUrl: './sidebar.component.html',
8 styleUrls: ['./sidebar.component.scss']
9})
10export class SidebarComponent {
11 generalService = inject(GeneralService)
12}
// In content.component.ts import { Component, OnInit } from '@angular/core'; import { GeneralService } from '../general.service'; @Component({ selector: 'app-content', templateUrl: './content.component.html', styleUrls: ['./content.component.scss'] }) export class ContentComponent { generalService = inject(GeneralService) }
1// In content.component.ts
2import { Component, OnInit } from '@angular/core';
3import { GeneralService } from '../general.service';
4
5@Component({
6 selector: 'app-content',
7 templateUrl: './content.component.html',
8 styleUrls: ['./content.component.scss']
9})
10export class ContentComponent {
11 generalService = inject(GeneralService)
12
13}
5- Subscribe to onButtonClick
subject in SidebarComponent: Now in sidebar.component.ts
implement the OnInit
life cycle hook, define property headingVisible
( default value true
).
Next in the ngOnInit
method, subscribe to the onButtonClick
subject and set the headingVisible
property to true
in the callback function of that subscribe function.
// In sidebar.component.ts import { Component, OnInit, inject } from '@angular/core'; import { GeneralService } from '../general.service'; @Component({ selector: 'app-sidebar', templateUrl: './sidebar.component.html', styleUrls: ['./sidebar.component.scss'] }) export class SidebarComponent implements OnInit { headingVisible = false; generalService = inject(GeneralService) ngOnInit(): void { this.generalService.onButtonClick.subscribe(heading => { this.headingVisible = true; }); } }
1// In sidebar.component.ts
2import { Component, OnInit, inject } from '@angular/core';
3import { GeneralService } from '../general.service';
4
5@Component({
6 selector: 'app-sidebar',
7 templateUrl: './sidebar.component.html',
8 styleUrls: ['./sidebar.component.scss']
9})
10export class SidebarComponent implements OnInit {
11
12 headingVisible = false;
13 generalService = inject(GeneralService)
14
15 ngOnInit(): void {
16 this.generalService.onButtonClick.subscribe(heading => {
17 this.headingVisible = true;
18 });
19 }
20
21}
6- Add heading in sidebar component: In the sidebar.component.ts
we will add an heading based on condition. If headingVisible
is set to true then the heading would be visible otherwise it will be hidden.
<!-- in sidebar.component.html --> @if(headingVisible){ <h1>Heading from sidebar component</h1> }
1<!-- in sidebar.component.html -->
2@if(headingVisible){
3 <h1>Heading from sidebar component</h1>
4}
7- Add button in sidebar component to trigger the event: Now in sidebar.component.html
, we need to add <button>
tag and register the click event that will then call the next
function of onButtonClick
subject from GeneralService
.
<!-- In sidebar.component.html --> <button (click)="generalService.onButtonClick.next('')">Show sidebar heading</button>
1
2<!-- In sidebar.component.html -->
3<button (click)="generalService.onButtonClick.next('')">Show sidebar heading</button>
4
So here as soon as the button is clicked then the subject onButtonClick
is triggered that sends signal to all subscriptions to it. In our case, we have subscribed to it in the sidebar.component.ts
, so the callback function in that subscription would be executed that would set the value of the showHeading
to true
and hence will cause the heading tag visible in the html template file.
====
This is just a brief introduction to calling functions between components in Angular. To explore more advanced techniques and examples, subscribe to my YouTube channel for more Angular tutorials and tips. Don't forget to like and share this post with your fellow Angular developers!
Like, Share, Subscribe!
Source Code: https://github.com/ayyazzafar/angular_17_tutorials_code/tree/call_function_from_another_component