Generate a new component within another dynamically generated component

In my endeavor to dynamically create a component within another dynamically created component, I am facing a unique challenge.

Below is the code snippet:

export class DefaultLayoutComponent {

    constructor(private cdRef: ChangeDetectorRef, public defaultLayoutService: DefaultLayoutService,
    private resolver: ComponentFactoryResolver) {
    }

    @ViewChild("appAsideContainer", { read: ViewContainerRef }) appAsideContainer: ViewContainerRef;

    ngOnInit() {

        this.defaultLayoutService.e_openAppAside.subscribe(params => {

            let appAsideRef;

            if (this.appAsideContainer.length == 0) {
                const appAsideFactory = 
                this.resolver.resolveComponentFactory(CustomAppAsideComponent);
                appAsideRef = this.appAsideContainer.createComponent(appAsideFactory);
            }

            let appAsideComponent = <CustomAppAsideComponent>appAsideRef.instance;

            //dynamically create comp.
            const factory = this.resolver.resolveComponentFactory(params.type);
            let component = appAsideComponent.container.createComponent(factory);

            //add input values to components
            if (params.inputs) {
                for (let p in params.inputs) {
                    component.instance[p] = params.inputs[p];
            }


        });        
    }
 }

The issue I am encountering is that some members of appAsideComponent cannot be accessed as it seems to not be fully instantiated.

https://i.sstatic.net/nPALf.png

The relevant CustomAppAsideComponent code:

export class CustomAppAsideComponent {
  
  constructor() {

  }

  @ViewChild("container", { read: ViewContainerRef }) public container: ViewContainerRef;
}

And its associated markup:

<app-aside [fixed]="true" [display]="false">
    <ng-template style="border: solid 2px;" #container></ng-template>
</app-aside>

app-aside generates a sidebar that opens vertically to the right.

I can successfully create other components using this method, but hitting a snag with this particular one. Both AppAsideComponent and CustomAppAsideComponent are included in the module's entryComponent

Is there something obvious that I may be overlooking?

Answer №1

To tackle this issue, you need to implement the ngAfterViewInit life cycle hook in the initially generated dynamic component. In case you dynamically generate the first dynamic component, you must create a second dynamic component on the native element of the dynamic components.

<!-- app.component.html -->
<p>Page1</p>
<ng-container #sample1></ng-container>
/* app.component.ts */
import {  
    Component,  
    Input,  
    OnInit,  
    ViewChild,  
    ComponentFactoryResolver,  
    OnDestroy,  
    ViewContainerRef  
} from '@angular/core';  
import {  
    Page1Component  
} from './page1/page1.component';  

@Component({  
    selector: 'app-root',  
    templateUrl: './app.component.html',  
    styleUrls: ['./app.component.scss']  
})  
export class AppComponent {  
    title = 'dynamicloader';  
    @ViewChild('sample1', {  
        read: ViewContainerRef,
        static: false  
    }) sample: ViewContainerRef;  
    constructor(private componentFactoryResolver: ComponentFactoryResolver) {}  
    ngOnInit() {  
        this.sample.clear();  
        let page1ComponentFactory = 
 this.componentFactoryResolver.resolveComponentFactory(Page1Component);  
        let page1ComponentRef = this.sample.createComponent(page1ComponentFactory);    
    }  
} 
<!-- page1.component.html -->
<p>Page2</p>
<ng-container #sample2></ng-container>
/* page1.component.ts */
import {  
    Component,  
    Input,  
    OnInit,  
    ViewChild,  
    ComponentFactoryResolver,  
    OnDestroy,  
    ViewContainerRef,
    AfterViewInit
} from '@angular/core';  
import {  
    Page2Component  
} from './page2/page2.component';  

@Component({  
    selector: 'app-page1',  
    templateUrl: './page1.component.html',  
    styleUrls: ['./page1.component.scss']  
})  
export class Page1Component implements AfterViewInit {   
    @ViewChild('sample2', {  
        read: ViewContainerRef,
        static: false  
    }) sample2: ViewContainerRef;  
    constructor(private componentFactoryResolver: ComponentFactoryResolver) {}  
    ngAfterViewInit() {  
        this.sample2.clear();  
        let page2ComponentFactory = 
 this.componentFactoryResolver.resolveComponentFactory(Page2Component);  
        let page2ComponentRef = this.sample2.createComponent(page2ComponentFactory);
    }  
} 

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

Using Angular to send a text to an injection service

i have developed a generic CRUD service that utilizes HttpClient through Dependency Injection (DI). However, I need to include another value in the constructor of this service. How can I achieve this? the issue arises when attempting to define this additi ...

The element ''ag-grid-angular'' is unrecognized:

After using ag-grid successfully for a few months, I attempted to integrate a grid from a previous project into an Angular template like the one found in ngx-admin: ngx-admin This is how the template is structured: https://i.sstatic.net/Mfjw8.png I tr ...

Best Practices for utilizing search feature in Angular version 13

Can someone please guide me on the correct way to implement search functionality? I want the results to be displayed in a separate component and prevent the user-entered value from being refreshed for further searches. https://i.sstatic.net/bPqUr.jpg Thi ...

Host several Angular Docker containers on a single server using Nginx

I currently have a setup with a single VM running three docker containers, two of which are Angular apps. Each container has its own nginx configuration, while the VM itself has an nginx configuration that manages SSL and forwards traffic to each docker co ...

Adding TypeScript to your Vue 3 and Vite project: A step-by-step guide

After setting up my project by installing Vue and Vite using the create-vite-app module, I decided to update all the packages generated by 'init vite-app' to the latest RC versions for both Vue and Vite. Now, I am interested in using TypeScript ...

Angular 2 Route offers a blueprint for creating a Component template

Is it possible to assign a specific template to a component within a route in Angular 2? I am working on a component that has the same controller functionality across three different views. My goal is to use the same component for all three views, but wit ...

Continuous Advancement Meter

I have implemented a progress bar, but I am encountering some issues with it. The progress bar is supposed to complete in 5 seconds. However, the value updates every second rather than continuously, causing it to pause intermittently. DEMO HTML <dx-p ...

Distribute the capabilities of the class

Is there a way to transfer the functionalities of a class into another object? Let's consider this example: class FooBar { private service: MyService; constructor(svc: MyService) { this.service = svc; } public foo(): string { ...

Trigger event (or other method) from deep nested child component in Angular 9

In my AngularJS application, I have a structure that consists of an Angular component (main) with a child component and a grandchild component. When a click event occurs in the grandchild component, I need to emit the event to the AngularJS application. ...

There will be no further upgrades available for Angular CLI after version 1.6.0

Based on the latest information from npm, the current version of @angular/cli is v6.2.5. Upon running ng -v, the output shows: _ _ ____ _ ___ / \ _ __ __ _ _ _| | __ _ _ __ / ___| | |_ _| / △ &b ...

Incorporate form controls within a table and implement merging capabilities in Angular 9

Can I insert form controls within table cells, and implement a merge feature for these table cells? For instance, if I merge two cells, will one of the controls extend to fill the vacant space? I am looking to create a basic spreadsheet with cell mergi ...

The splice method in JavaScript is not behaving as anticipated

, While experimenting with JavaScript splice methods, I encountered an issue where it was not removing elements from an array as expected. Currently, it only deletes the last element from the array even when providing a specific index to delete. The conso ...

Navigate to a specific element on a webpage upon the page's initial load in Angular 2

Is there a way to navigate from one page to another and instantly jump to a specific control in the middle of the destination page? Typically, we would use a hashtag "#" followed by the name or ID of the control. Unfortunately, this method doesn't wo ...

Issue with Angular 7 Universal: components inside are failing to display

I have successfully implemented Angular 7 Universal with dynamic server-side rendering. However, I am facing an issue where dynamic components within the main component being rendered on the server are not rendered themselves. Here is an example of the re ...

"Selecting the appropriate version of Angular for your project

Hello there, I am a beginner in this field and have a question. I am currently working on an app using Ionic with Angular version 4. I am considering switching to Angular version 1. Can you help me out with the steps to do so? Thank you! ...

Switch the ngClass on the appropriate ancestor element for the dropdown menu

Utilizing Angular CLI version 8.3.0, I aim to construct a sidebar featuring a drop-down menu. My objective is to apply the "open" class to toggle the opening of the drop-down section. However, the current challenge I am encountering is that when I click to ...

Fetching URL from Right Before Logging Out in Angular 2 Application

I am struggling to capture the last active URL before logging a user out of my Angular 2 app. My goal is to redirect them back to the same component or page once they log back in. Currently, I am using this.router.routerState.snapshot['url'] to r ...

[karma]: Oops! We've encountered a snag - the module [expose-loader?jQuery!jquery] couldn't be

Currently, I am working on setting up karma tests for typescript. karma.conf.js module.exports = function (config) { config.set({ frameworks: ['jasmine', 'karma-typescript'], files: [ {pattern: 'sr ...

Tips for efficiently displaying and handling vast quantities of information within an Angular 2 table

I am currently working on the development of an Angular 2 application that requires displaying a large amount of data in a scrollable table. The data is stored in an array within my component class: export class AppComponent { clients: any[] = []; ...

Utilizing WebPack 5 in conjunction with Web workers in a React/Typescript environment

Can someone help me figure out how to make a web worker function properly with create-react-app, Typescript, and Webpack 5? I've been struggling with limited documentation and can't seem to find a clear explanation. I'm trying to avoid using ...