6

I am having problem with dynamic component rendering with 'ViewContainerRef' in a gridster item.

I have implemented a component which takes component reference, inputs and outputs as input and creates this given component inside itself.

ex: <app-component-loader [compRef]="{ref: ExComponent}"><app-component-loader>

inside component loader onInit callback I have

if (this.compRef && this.compRef.ref) {
        this._componentFactory = this._componentFactoryResolver.resolveComponentFactory(this.compRef.ref);

        const instance  = this.viewContainer.createComponent(this._componentFactory, 0).instance;

        console.log(instance);

        if (this.compInputs) {
            Object.getOwnPropertyNames(this.compInputs).forEach(field => {
                instance[field] = this.compInputs[field];
            });
        }

        if (this.compOutputs) {
            Object.getOwnPropertyNames(this.compOutputs).forEach(field => {
                instance[field].subscribe(e => {
                    this.compOutputs[field]();
                });
            });
        }
    }

I am using this component laoder into gridster item component like:

<gridster [options]="gridsterConfig">
            <gridster-item [item]="widget" *ngFor="let widget of board.widgets">
                <app-component-loader [compRef]="{ ref: registry.get(widget.outletComponent) }" [compInputs]="{ widget: widget }" [compOutputs]="{ removeCallback: widgetRemoveCallback.bind(this), changed: widgetChanged.bind(this) }"></app-component-loader>
            </gridster-item>
 </gridster>

It is working fine and loading gridster items and their outlet components while developing.

Hovewer today I tried to build my app with ng build --prod and deploy to server I recognize that my component loader is not creating components.

Am I missing something special to dynamic component creation for production builds. I have searched about this but got nothing.

Before implementing my component loader component I was doing this component creation with ng-dynamic-component package and again it was working fine while developing but got exception which saying instance of component is NULL when production.

I think it is not the problem that the way of creating rendering the components but need help.

Additionally, my dependencies are:

"@angular/animations": "^5.2.9",
"@angular/cdk": "^6.0.2",
"@angular/common": "^5.2.9",
"@angular/compiler": "^5.2.9",
"@angular/core": "^5.2.9",
"@angular/flex-layout": "^5.0.0-beta.14",
"@angular/forms": "^5.2.9",
"@angular/http": "^5.2.9",
"@angular/platform-browser": "^5.2.9",
"@angular/platform-browser-dynamic": "^5.2.9"

"@angular/cli": "^1.7.3",
"@angular/compiler-cli": "^5.2.9",
"@angular/language-service": "^5.2.9",

Thank you all.

oktykrk
  • 111
  • 1
  • 11
  • Hi, did you fix this , can you help me I am facing the same issue [I add a question here](https://stackoverflow.com/questions/51754722/dynamic-load-component-not-work-in-production) – AAHN Aug 09 '18 at 07:07
  • couldn't fix sadly. I just build my app with "ng build" without "--prod" flag for now. – oktykrk Aug 09 '18 at 11:58
  • 1
    I solve it :) thanks check the answer on my question [here](https://stackoverflow.com/a/51763377/4184713) – AAHN Aug 10 '18 at 10:33
  • Thank you very much man. It solved my problem too:) I have packaged this solution as an npm package for reuse. Find the package [here](https://www.npmjs.com/package/ngx-dynamic-host). – oktykrk Sep 28 '18 at 08:23

1 Answers1

0

This is what working for me, Create a directive for view as below, In your app-component-loader.ts onInIt

@ViewChild(DynamicHostDirective) 
   hostDirective: DynamicHostDirective

ngOnInIt(){
if (this.compRef && this.compRef.ref) {
        this._componentFactory = this._componentFactoryResolver.resolveComponentFactory(this.compRef.ref);

        const instance  = this.hostDirective.viewContainerRef.createComponent(this._componentFactory).instance;

        console.log(instance);

        if (this.compInputs) {
            Object.getOwnPropertyNames(this.compInputs).forEach(field => {
                instance[field] = this.compInputs[field];
            });
        }

        if (this.compOutputs) {
            Object.getOwnPropertyNames(this.compOutputs).forEach(field => {
                instance[field].subscribe(e => {
                    this.compOutputs[field]();
                });
            });
        }
    }
    }

In your app-component-loader.html,

<ng-template dynamic-host></ng-template>

finally host directive

import {Directive, ViewContainerRef} from '@angular/core';

@Directive({
  selector: '[dynamic-host]',
})
export class DynamicHostDirective {
constructor(public viewContainerRef: ViewContainerRef){}
}

Hope it helps

  • Thank you for the help. I will try your suggestion as soon as possible and give feed back to you. – oktykrk May 30 '18 at 08:22
  • 1
    I just tried your solution @user9576114 but got the result same. It works fine but when build production components are not rendering. I build the app with "ng build" not not "ng build --prod" for now. Thank you for your help. – oktykrk Jun 11 '18 at 07:32