Child components that are dynamically generated should be able to utilize functions from their parent component

I am working on a project that involves 3 TS files: 1) Parent-Component.ts 2) Child-Component.ts 3) Service.ts

In the Parent-Component.ts file, there is a button click event that calls a function in Service.ts. This function dynamically creates the Child Component using the code provided below.

Parent-Component.html:

<div class="form-group">
<div class="row">
<div class="mt-3 col-md-12">
<h3>{{ i18n.common + 'Filter' | dynamicTranslate }}</h3>
<div #filterCriteria></div>
</div>
</div>
</div>
<div class="row filter-actions mb-3">
<div class="col-md-12">
<button type="button" **(click)="appendAdditionalFilter()" **>
<i class="fa fa-plus"></i></button>     <strong>&nbsp;{{ 'Add Filter' }}</strong>
<button type="button" class="btn btn-primary ml-2" 
(click)="appendFilterFromService()">{{ i18n.common + 'Apply Filter' | dynamicTranslate }}
</button>
</div>
</div>

When the "Add Filter" button is clicked, the appendAdditionalFilter() function is called in Parent-Component.ts, which then calls Service.ts to create the child component dynamically.

Parent-Component.ts:

@ViewChild('filterCriteria', { read: ViewContainerRef, static: false})
filterCriteriaContainer: ViewContainerRef;
appendAdditionalFilter() {    
this.filterCriteriaContainer = this.filterGridService
.addFilter(this.filterCriteriaContainer, this.MetaData, this.i18n.Test1, 
this.Test2);
}

Service.ts:

addFilter(
filterCriteriaContainer: ViewContainerRef,
MetaData: Array<FieldMetaDataDto>,
Test1: string,
Test2?: number,
filter?: FilterDto,
): ViewContainerRef {
const comp = this.componentResolver.resolveComponentFactory(ChildComponent);
const filterCriteria = filterCriteriaContainer.createComponent(comp);

filterCriteria.instance.ref = filterCriteria;

filterCriteria.instance.translationKeyBase = Test1;

filterCriteria.instance.filterMetadata = MetaData;
filterCriteria.instance.dataTarget = Test2;
  
return filterCriteriaContainer;
}

There is also a "Remove" button click event in the Child Component that needs to call the appendFilterFromService() function in Parent-Component.ts.

Child-Component.html:

<div>
<button (click)="remove()" type="button" class="btn btn-action btn-small">
<i class="fa fa-minus"></i>
</button>
<strong>{{i18n.common + 'Remove Filter' | dynamicTranslate }} </strong>
</div>

Child-Component.ts:

ref: ComponentRef<ChildComponent>;
remove(){
this.ref.destroy();
//Need to call Parent-Component.ts function appendFilterFromService() here//
}

Any assistance would be greatly appreciated.

Answer №1

If your service requires additional parameters from the parent component, one approach is to trigger an event from the child component that can be captured by the parent.

To set up this communication, you need to define an @Output binding in the child component like so:

  @Output() removeEvent = new EventEmitter<string>();

In the child's HTML template, include a click binding for the "Remove" button as follows:

<button type="button" (click)="onRemove()">Remove</button> 

The method within the child component that emits the event is defined as:

  onRemove(): void {
    this.removeEvent.emit('remove');
  }

In the parent component's HTML, specify the method to call when the child emits the event:

  <app-child (removeEvent)="onRemoveFromChild($event)"> </app-child>

Now, within the parent component, you can trigger actions based on events emitted by the child:

  onRemoveFromChild(event: string): void {  
    this.appendAdditionalFilter();
  }

A simplified Stackblitz example is provided for reference.

Update

For dynamic components, after creating the component, you will receive a reference like this:

const componentRef = this.container.createComponent(ChildComponent);

With this reference, you can access the instance and its @Output events like this:

componentRef.instance.removeEvent.subscribe((event: string) => {
  this.service.addFilter();
});

Remember to unsubscribe from these events when the component is destroyed.

A modified version of the original Stackblitz demo is available for further insight.

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

What is the method for retrieving a typed property that is not defined in a non-instantiated class (DTO)?

I am currently working on implementing a logic to validate whether all HTTP body properties are mandatory in my DTO. I have managed to access the request body using a custom decorator and an interceptor in Nestjs, but during validation, I face the challeng ...

What is the best way to include a search bar within a dropdown menu?

I have successfully used a dropdown feature with data display through *ngFor. Now, I am looking to incorporate a search bar into the dropdown functionality. https://i.sstatic.net/NR38T.png Here is the HTML code snippet: <ion-select item-end> ...

Why do users struggle to move between items displayed within the same component in Angular 16?

Lately, I've been immersed in developing a Single Page Application (SPA) using Angular 16, TypeScript, and The Movie Database (TMDB). During the implementation of a movies search feature, I encountered an unexpected issue. Within the app\servic ...

Sortable layouts and tables in Ionic 3

I found a great example of an Ionic table that I'm using as reference: https://codepen.io/anon/pen/pjzKMZ <ion-content> <div class="row header"> <div class="col">Utility Company Name</div> <div c ...

Retrieving a pair of data points from a Vue <select> event when it changes

I am facing an issue with a dropdown menu that is using an array with key:value pairs. I want the dropdown to only show values, but when a selection is made, I need to pass both the value and the key using the @change event. <select @change=" ...

Is there a RxJS equivalent of tap that disregards notification type?

Typically, a tap pipe is used for side effects like logging. In this scenario, the goal is simply to set the isLoading property to false. However, it's important that this action occurs regardless of whether the notification type is next or error. Thi ...

If the table spans multiple pages, a top margin will be added to ensure proper formatting. This feature is implemented using jspdf-autotable

I have encountered an issue with my PDF function where using multiple tables and the didDrawPage() hook to add headers and footers results in images being drawn multiple times in the header due to the multiple tables. To resolve this, I created a separate ...

State remains unchanged despite calling setState

When working with React, I encountered an issue in my function called setTitleAndBody. Even though the object result is being logged correctly and displaying the title and body information in the developer console, the setState method is not updating the ...

Creating a currency input field in HTML using a pattern textbox

In a project using HTML, Angular 2, and Typescript, I am working with a textbox. How can I ensure that it only accepts numbers along with either one dot or one comma? The input should allow for an infinite number of digits followed by a dot or a comma and ...

Fetching Form Data from Angular Service

My project structure consists of a FATHER component with a stepper, each step-page containing a CHILD component with a FORM. In one page, the CHILD component has another CHILD with yet another FORM. At the final step of the stepper, there is a SUBMIT butt ...

Guide on connecting ngrx/store to an angular router guard

As someone who is new to ngrx/store, I am embarking on my initial project utilizing this tool. After successfully setting up my angular project with ngrx/store, I discovered how to dispatch a load action following the initialization of my main component: ...

Error encountered in Vue 3 typescript: Uncaught TypeError - this.$on function is not defined in this context

Just set up a fresh installation of Vue 3 using vue-cli and typescript. Everything seems to be running smoothly, but as soon as I incorporate the https://vue-select.org/ package, I encounter this error in the browser console: Uncaught (in promise) TypeErro ...

Choose historical dates with the dl-date-time-picker component within an Angular application

In my Angular 7 project, I have integrated a datetimepicker component called dl-date-time-picker. I want to prevent users from selecting previous dates in the date and time picker. Although I tried using the [selectFilter] attribute for this purpose, it en ...

Displaying icons representing different countries using Angular framework

Seeking assistance with Angular - I obtained a collection of country icons (svg format) from flat icon and intend to display them based on the respective countries in my project. With 870 icons, what would be the simplest approach to accomplish this with ...

Can the dragging functionality be turned off for a specific sub-element of cdkDrag?

Currently, I am utilizing Angular CDK drag-drop features from Angular Material. I have been exploring the documentation available here. One issue that has arisen is the inability to select text within an input field of a draggable element using the mouse. ...

React Typescript Context state isn't refreshing properly

Struggling to modify my context state, I feel like I'm overlooking something as I've worked with context in the past. The challenge lies in changing the 'isOpen' property within the context. You can view my code here: CodeSand **app.ts ...

What strategies can be used to handle unsaved entities when an ID attribute is required?

In my React application, the data I am working with is structured as follows: interface BookCase { id: number; bookShelves: BookShelf[]; } interface BookShelf { id: number; } Each bookcase and bookshelf has an id property that serves as the k ...

What could be causing Typescript to inaccurately infer the type of an array element?

My issue revolves around the object named RollingStockSelectorParams, which includes arrays. I am attempting to have TypeScript automatically determine the type of elements within the specified array additionalRsParams[title]. The main question: why does ...

Disabling the ESC key from clearing input fields in Bootstrap-5: A step-by-step guide

I have come across this code snippet for a search field: <form class="container" role="search"> <div class="row"> <div class="col-12"> <input name="searchItem" #search ...

refresh the React component without having to refresh the entire webpage

Hey there, I have a component with a function called "handleAvatarUpload". Currently, when there is a change, the entire page reloads instead of just the component. Is there a way to reload only the component without refreshing the whole page? import { us ...