Executing a Parent Function from a Child Component in Angular 11

I have successfully passed values between Angular components using Input/Output several times before, but I am currently facing a unique situation for which I cannot find a solution:

There are two components involved:

  1. home.component (parent component)

The parent component contains another navigation component that displays tabs from an external library. This navigation component is responsible for loading the child component: "task.component".

html file:

<div>
<app-tabs [tabs]="tabs" [activeTab]="activeTab" (id)="onId($event)"></app-tabs>
</div>

ts file:

onId($event) {
    // $event would contain the id obtained in the child component
}
  1. tasks.component (child component)

The child component has a button click event that needs to communicate with the parent component:

html file:

<button type="button" (click)="play('task/play', 30)">Play</button>

ts file:

@Output() id= new EventEmitter<number>();
play(url: string, id: number) {
this.tasksService.playTask(url).subscribe(
  response => {
    // Here, I need to access a method in the parent component.
    // this.id.emit(id);
  },
  err => {
  }
);
}

In previous cases, passing parameters between child and parent components was straightforward because I used custom components. However, when working with an intermediate tab component, this becomes a challenge. It seems that directly passing the "Output" to the "app-tabs" component is not feasible.

Any suggestions on how to overcome this issue?

Answer №1

It appears that a child component (or grandchild component) is nested within a child route.

To address this issue, one approach could be to utilize a shared service for communication between the child component and its parent (or any other component in the application).

To achieve this, we would require an injectable service (or integrate it into an existing service):

In notification.service.ts:

@Injectable()
export class NotificationService {
  _taskPlayed$ = new Subject<number>();
  
  get taskPlayed$() {
    return this._taskPlayed$.asObservable();
  }
  
  taskPlayed(id: number) {
    this._taskPlayed$.next(id);
  }
}

Ensure to add this service to the module providers.

Subsequently, the service can be injected into the child (or any desired) component, allowing us to invoke the taskPlayed method to trigger a new value/event in the observable.

Thus, in child.component.ts:

export class ChildComponent {
  constructor(private notificationService: NotificationService) {}
  
  playTask() {
    this.notificationService.taskPlayed(1);
  }
}

Similarly, we inject the service into the parent (or any other relevant component), subscribing to the taskPlayed$ observable from the service (remembering to unsubscribe upon component destruction).

Hence, in parent.component.ts:

export class ParentComponent implements OnInit, OnDestroy {
  subscription!: Subscription;
  
  constructor(private notificationService: NotificationService) {}
  
  ngOnInit(): void {
    this.subscription = this.notificationService.taskPlayed$.subscribe((id) => {
      // perform actions with id...
      ....
    });
  }
  
  ngOnDestroy(): void {
    this.subscription?.unsubscribe();
  }
}

In the provided example, only the id value is transmitted via the Observable, but more complex objects can also be passed.

export class NotificationService {
  _taskPlayed$ = new Subject<{ id: number, title: string }>();
  
  get taskPlayed$() {
    return this._taskPlayed$.asObservable();
  }
  
  taskPlayed(task: {id: number, title: string}) {
    this._taskPlayed$.next(task);
  }
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Retrieve the instance from the provider using its unique key without needing to inject its dependencies

I created a custom class called PermissionManager, which takes a list of Voter interfaces as an input in its constructor. export interface Voter { vote(): bool; } export class PermissionManager { constructor(private readonly ...

Sort through the files for translation by utilizing a feature within Typewriter

I am looking to implement Typewriter in a project that involves translating many C# files into TypeScript using WebEssentials. Is there a way to configure the template so that only class files containing a specific attribute are translated in this mann ...

A guide on specifying the data type for functions that receive input from React Child components in TypeScript

Currently, I am faced with the task of determining the appropriate type for a function that I have created in a Parent Component to retrieve data from my Child Component. Initially, I resorted to using type: any as a solution, although it was not the corr ...

What could be causing the itemClicked() function to malfunction intermittently in Ionic2 / Angular2?

The issue at hand One common problem experienced with Angular's (click) functionality is that it may not work properly when <div> tags are utilized. In certain situations, multiple clicks might be required. I encountered the same problem mysel ...

Obtain precise measurements of a modified image using the Sharp library

My Cloud Function successfully resizes images uploaded to Cloud Storage using Sharp. However, I am facing an issue with extracting metadata such as the exact height and width of the new image. I am contemplating creating a new function that utilizes diff ...

The function for batch insertion only functions with Postgresql and SQL Server databases

I am a beginner in JavaScript and I am currently working on creating a new restaurant. I have come across a code snippet that inserts a relation into a join-table: await newRestaurant.$relatedQuery('tags', trx).relate(tagIds); Is it not possible ...

React TypeScript Context - problem with iterating through object

Can someone please help me with an error I am encountering while trying to map an object in my code? I have been stuck on this problem for hours and despite my efforts, I cannot figure out what is causing the issue. Error: const categoriesMap: { item: ...

How to form an array using rxjs before the adding sequence is completed

I am currently exploring a way to utilize rxjs to achieve the following scenario: You have two observables, onAddObs and onRemoveObs. Assume that onAddObs.next() is triggered multiple times, adding "A", "B", "C". I aim to then extract ["A", "B", "C"]. .t ...

Retrieving template variable within a directive's host listener function

Can 'habitCellInfo' be accessed from the template within the onvalueChanged host listener? <div *dxTemplate="let habitCellInfo of 'habitEditCellTemplate'"> <dx-select-box (onValueChanged)=" onHabitEdi ...

Testing TaskEither from fp-ts using jest: A comprehensive guide

Entering the world of fp-ts, I encounter a function (path: string) => TaskEither<Erorr, T> that reads and parses configuration data. Now, my challenge is to create a test for this process. Here is what I have tried so far: test('Read config& ...

Jasmine attempting to access a nonexistent property

I created a very basic component: import { Component } from '@angular/core'; @Component({ selector: 'loading', templateUrl: './loading.component.html', styleUrls: ['./loading.component.scss'] }) export ...

Setting a global property within the complete method of an ngrx Angular subscriber is a helpful technique to ensure that

Currently, I have a global property called loadingIndicatorsearchVisible = false;. In addition, there is a method containing an observable, where I manipulate the loadingIndicatorsearchVisible to display or hide a loading panel. search(){ this.loadingI ...

Issue with implicitly assigning 'any' type to overloaded variadic generic function

We have some code snippets for you to review: export type actions = { abort: () => void; back: () => void; next: () => void; resume: () => void; }; class Sabar { public use<T1>(fn: (arg1: T1, ctx: object, actions: actions) =&g ...

Unable to retrieve React state within the callback function

As I work with the following components: const ParentComponent: React.FC = () => { // Setting newType to some value within the code const [newType, setNewType] = useState<any>(undefined); // Enabling addEdge to true in another part o ...

Unable to attach to 'leafletOptions' as it is unrecognized as a property of 'div'

It seems like I keep encountering this problem, which is often resolved by adjusting import statements. Right now, my imports look like this: import { LeafletModule } from 'node_modules/@asymmetrik/ngx-leaflet'; import * as L from 'leaflet& ...

Enhancing TypeScript Types with a custom method within an Angular 2 context

I am working on an Angular 2 project using the CLI. Currently, I am trying to add a custom method to the String type as shown below. interface String { customMethod(): number; } String.prototype.customMethod = function() { return 0; } Despite my ...

To run multiple environments with react-native-dotenv in a React Native project using Typescript, only the local environment is activated

Currently, I am facing an issue while trying to initialize my React Native app with TypeScript in three different environments - development, local, and testing. When I attempt to run APP_ENV=testing expo start or APP_ENV=development expo start, it always ...

ngModelChange not triggered when updating the model from a component

I am currently exploring Angular and trying to grasp the concept of connecting different controllers to update their values based on changes in one controller. In a specific scenario, I have a form with ngModel and I am attempting to utilize ngModelChange ...

The type 'Observable<any>' cannot be assigned to the type 'Observable<T>'

Here is the code I am working with: import {HttpClient} from '@ngular/common/http'; private httpClient: HttpClient; do_request(method: string, url: string, ...

This error message indicates that the certificate for Angular 13 has expired

After successfully installing Angular and verifying the version, I encountered an issue when attempting to run the command npm start. Despite multiple attempts at uninstalling and reinstalling everything, the problem persists. Running npm install also resu ...