How to refer to a dynamic instance of @ContentChild in Angular 2

I am currently working with Angular 2.0.1.

One of my components can accept any other component using <ng-content>, and this functionality is working well.

However, I face a challenge when trying to reference the injected component.

If I knew that only one component would ever be passed through <ng-content>, I could simply declare:

@ContentChild(MyComponent) dynamicTarget: IMyComponent;
. But since it could be any component (with the assumption that each injected component implements a specific interface), things get more complicated.

I also attempted using

<ng-content #dynamicTarget'>
and then referencing it like so:
@ContentChild('dynamicTarget') dynamicTarget: IMyComponent;
, but unfortunately, this returns undefined.

Does anyone have a solution on how I could inform Angular 2 that this element is an instance of a component so that I can proceed to call a function on it?

To provide more context to the scenario - I am developing a multi-step wizard that may contain various components as content, and my objective is to execute the validate function on the content (assuming such a function exists within the respective instances).

Answer №1

One technique could involve assigning the same #id to all dynamic components, such as using #thoseThings (similar to @Missingmanual).

PLUNKER (check the console for matches.)

@Component({
  selector: 'my-app',
  template: `
  <div [style.border]="'4px solid red'">
    I'm (g)Root.

    <child-cmp>
      <another-cmp #thoseThings></another-cmp>
    </child-cmp>
  </div>
  `,
})
export class App {
}


@Component({
  selector: 'child-cmp',
  template: `
    <div [style.border]="'4px solid black'">
        I'm Child.
      <ng-content></ng-content>
    </div>
  `,
})
export class ChildCmp {
  @ContentChildren('thoseThings') thoseThings;

  ngAfterContentInit() {
    console.log(this.thoseThings);

    this.validateAll();

    if(this.thoseThings){
     this.thoseThings.changes.subscribe(() => {
       console.log('new', this.thoseThings);
     }) 
    }
  }

  validateAll() {
    this.thoseThings.forEach((dynCmp: any) => {
      if(dynCmp.validate)
       dynCmp.validate();  // calls validate function if it exists in the component
    });
  }
}


@Component({
  selector: 'another-cmp',
  template: `
    <div [style.border]="'4px solid green'">
        I'm a Stranger, catch me if you can.
    </div>
  `,
})
export class AnOtherCmp {
}

Answer №2

@NgModule({
  imports: [ BrowserModule ],
  declarations: [ App, Parent, Transcluded1, Transcluded2 ],
  providers: [
    {provide: TranscludedBase, useExisting: Transcluded1, multi:true},
    {provide: TranscludedBase, useExisting: Transcluded2, multi:true}
  ],
  bootstrap: [ App ]
})

Plunker demonstration

  • You have the option to employ dynamic creation of components, detailed in this post: Angular 2 dynamic tabs with user-click chosen components, which encompasses wizard steps instead of traditional tabs.

  • Alternatively, you can explicitly pass elements to an input rather than solely projecting them:

See example on Plunker

Answer №3

If every component has a validate function and implements the same interface like IValidate, you can use the following approach:

@ContentChild('IValidate') dynamicTarget: IValidate;
// ...
this.dynamicTarget.validate();

Angular is indifferent to the specific class as long as it adheres to the required interface.

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

Your global Angular CLI version (6.1.2) surpasses that of your local version (1.5.0). Which version of Angular CLI should be used locally?

I am experiencing an error where my global Angular CLI version (6.1.2) is higher than my local version (1.5.0). Can someone provide assistance with this issue? Below are the details of my local versions: Angular CLI: 1.5.0 Node: 8.11.3 OS: win32 ia32 Ang ...

Encountering issues when attempting to activate npm start command in Ubuntu operating system

Recently delving into the world of Angular2, I've been working on setting up an AngularJS 2.0 project on Ubuntu. I made sure to install npm in the root directory of my Angular2 app. However, when I attempt to run npm start, I encounter the following e ...

Creating a Component with a flexible template: (Using transclusion and an inline template)

Trying to come up with a solution for creating a component that can work with dynamic template strings and access local variables within the template has proven to be quite challenging. No matter what approach I take, I always seem to struggle with getting ...

I want to establish the identical response output field name in NestJS by utilizing the @Expose decorator from class-transformer

My Entity definition currently looks like this: export class ItemEntity implements Item { @PrimaryColumn() @IsIn(['product', 'productVariant', 'category']) @IsNotEmpty() itemType: string; @PrimaryColumn() @IsU ...

What materials are required in order to receive messages and information through my Contact page?

Currently, I am pondering the optimal method for gathering information from my Contact page. I have already created a form; however, I'm unsure how to send the gathered data to myself since I am relatively new to Web development. Angular is the framew ...

Guide on integrating an element into a different element in a Vue 3 Tree Viewer

In my current setup, I've implemented a TreeView component that holds a tree. Each tree entry includes Children with their own unique label, perm, and further children. Take a look at an example of the tree: App.vue let tree = ref({ label: 'o ...

Error: Angular ngFor directive not displaying list item

I am trying to create a simple ul element with some li items in it using a component I designed: import { Component } from '@angular/core'; @Component({ selector: 'skin', templateUrl: './skin.component.html', styleUrls: ...

Encountering issues when attempting to set up graphqlExpress due to type

This is my first experience using GraphQL with Express. I have created a schema: import { makeExecutableSchema } from "graphql-tools"; import { interfaces } from "inversify"; const schema = ` type Feature { id: Int! name: String ...

Encountered an issue while setting up an object variable: Error - **'const' declarations must be initialized.**

When attempting to initialize an object and assign a value to it, I encountered an error while declaring the object. Error: 'const' declarations must be initialized. How can I properly initialize my object? Code: // Object export type DateRan ...

What is the predetermined time limit for an HTTP GET request made using the HttpClient module in Angular 2?

I'm currently investigating the default timeout for an HTTP GET request made with HttpClient in Angular 2. I need to determine if the timeout is occurring at the endpoint due to a large query or if it's caused by the request itself timing out. Un ...

What are the steps for integrating and expanding a JavaScript library using rollup, TypeScript, and Angular 2?

I am currently working on a project called angular2-google-maps-test and I am interested in integrating and expanding upon the JS library found at js-marker-clusterer npm install --save js-marker-clusterer It seems that this library is not structured as ...

The error TS2304 in @angular/common is indicating that the name 'unknown' cannot be found

I am struggling to revive an old project due to some errors. I am using Angular 5.2.9 for the build, but these errors keep popping up. If anyone can offer assistance, I would greatly appreciate it. This is how my package.json file appears: "dependencies" ...

Storing response data as a variable in TypeScript with Angular 2 can be achieved by declaring a variable

I am unfamiliar with TypeScript and need assistance. After performing a POST request, I received an _id that I now need to use to execute a PUT function for play pause. When the play pause button is clicked, the response should be sent to the server. Below ...

Utilizing Angular's mat-slide-toggle along with a numeric input form

Check out this snippet of Angular code : <mat-slide-toggle formControlName="device_maintenance_mode" [(ngModel)]="isChecked">Maintenance Mode : {{isChecked}} </mat-slide-toggle> <mat-fo ...

Create an interactive and responsive user interface for Object using the Angular framework

After receiving a JSON Object from an API call with multiple string values, I need to create an Interface for this Object in the most efficient way possible. Rather than manually writing an Interface with 100 keys all of type string, is there a quicker a ...

The issue of a mocked MobX store in Jest not resetting between tests is causing problems

I have a straightforward login component and a MobX store that holds user information. I am testing the integration using Jest. The application is built with Create React App, so my tests are based on that. This is what my Login component looks like: cons ...

Issues with mat-input functionality within a mat-table in Angular 8

I'm encountering an issue with my mat-table. The input field within the table is not functioning properly. All rows are sharing the same input field, so when I type text into the box, it appears in all rows. Here is my code: <ng-container matColum ...

"Strange Type Conversion Behavior in next.js 13: Why is res.json() Converting Numbers to Strings

I have encountered a strange issue where no matter what I do, the fetched data is being partially converted to strings. For example, the 'bialko' and 'kcal' fields are supposed to be of type Float in Prisma, yet they are getting casted ...

Isolated Modules in Angular Version 17 and Beyond

Having worked with an earlier version of Angular, I am facing issues with my navbar routes not working properly on my Contact Page. Can someone shed some light on this for me? If you want to take a look at the code, here is the link: https://github.com/Lo ...

Searching through an array to find or filter items based on multiple conditions

Here is a dataset containing various types of information: [0: {lat: "37.829998", lng: "-122.003152", title: "Allocate", pairStatus: 1, …} 1: {lat: "37.829998", lng: "-122.003152", title: "Commission", pairStatus: 1, …} 2: {lat: "37.829998", lng: "-12 ...