Why adding a Material Module breaks the dynamic component insertion?











up vote
1
down vote

favorite












Here are two MCVEs on StackBlitz using dynamic component creation. I would like to understand why :





  • This works.

  • But this does not work, just after importing a Material Module (MatButtonModule) into the dynamically created module.


Does anyone have an idea?



Example that works



app.component.ts



import { Component, ChangeDetectionStrategy, OnDestroy, ChangeDetectorRef, ViewChild, ViewContainerRef, Input, Compiler, Injector, NgModuleRef, SimpleChanges, NgModule, ComponentFactoryResolver, ReflectiveInjector } from '@angular/core';
import { CommonModule } from '@angular/common';
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { HttpClientModule } from '@angular/common/http';
import { MatButtonModule } from '@angular/material';

@Component({
selector: 'my-app',
template: `
<ng-container
#viewContainerRef
></ng-container>
`,
})
export class AppComponent {
@ViewChild('viewContainerRef', { read: ViewContainerRef }) viewContainerRef: ViewContainerRef;

constructor(
private compiler: Compiler,
private injector: Injector,
private ngModuleRef: NgModuleRef<any>,
private changeDetectorRef: ChangeDetectorRef,
) {
}

ngOnInit() {
const template = `
<button
mat-button
[innerHTML]="'Click me!'"
>
</button>
`
this.viewContainerRef.clear();
const component = Component({
changeDetection: ChangeDetectionStrategy.OnPush,
template
})(class { });
const ngModule = NgModule({
imports: [
CommonModule,
BrowserModule,
BrowserAnimationsModule,
HttpClientModule,
],
entryComponents: [component],
declarations: [component]
})(class { });
this.compiler.compileModuleAndAllComponentsAsync(ngModule).then((factories) => {
const factory = factories.componentFactories[0];
const componentRef = this.viewContainerRef.createComponent(
factory,
this.viewContainerRef.length,
this.injector,
,
this.ngModuleRef
);
this.changeDetectorRef.detectChanges();
});
}
}


app.module.ts



import { NgModule, CompilerFactory, COMPILER_OPTIONS, Compiler } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { JitCompilerFactory } from '@angular/platform-browser-dynamic';

import { AppComponent } from './app.component';

export function createCompiler(compilerFactory: CompilerFactory) {
return compilerFactory.createCompiler();
}

@NgModule({
imports: [ BrowserModule, FormsModule ],
declarations: [ AppComponent ],
bootstrap: [ AppComponent ],
providers: [
{ provide: COMPILER_OPTIONS, useValue: {}, multi: true },
{ provide: CompilerFactory, useClass: JitCompilerFactory, deps: [COMPILER_OPTIONS] },
{ provide: Compiler, useFactory: createCompiler, deps: [CompilerFactory] },
],
})
export class AppModule { }


Example that does not work



Adds the MatButtonModule into the imports of the dynamic module :



app.component.ts



const ngModule = NgModule({
imports: [
CommonModule,
BrowserModule,
BrowserAnimationsModule,
HttpClientModule,
MatButtonModule,
],
entryComponents: [component],
declarations: [component]
})(class { });


Behavior



There are no errors, but the dynamic component seems to not be inserted (it is at least not visible).










share|improve this question
























  • that awkward moment a future reader looks at this and stackblitz is not available.
    – Stavm
    Nov 11 at 11:20










  • Thanks @Stavm, so I posted the code here too.
    – Hadrien TOMA
    Nov 11 at 11:21

















up vote
1
down vote

favorite












Here are two MCVEs on StackBlitz using dynamic component creation. I would like to understand why :





  • This works.

  • But this does not work, just after importing a Material Module (MatButtonModule) into the dynamically created module.


Does anyone have an idea?



Example that works



app.component.ts



import { Component, ChangeDetectionStrategy, OnDestroy, ChangeDetectorRef, ViewChild, ViewContainerRef, Input, Compiler, Injector, NgModuleRef, SimpleChanges, NgModule, ComponentFactoryResolver, ReflectiveInjector } from '@angular/core';
import { CommonModule } from '@angular/common';
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { HttpClientModule } from '@angular/common/http';
import { MatButtonModule } from '@angular/material';

@Component({
selector: 'my-app',
template: `
<ng-container
#viewContainerRef
></ng-container>
`,
})
export class AppComponent {
@ViewChild('viewContainerRef', { read: ViewContainerRef }) viewContainerRef: ViewContainerRef;

constructor(
private compiler: Compiler,
private injector: Injector,
private ngModuleRef: NgModuleRef<any>,
private changeDetectorRef: ChangeDetectorRef,
) {
}

ngOnInit() {
const template = `
<button
mat-button
[innerHTML]="'Click me!'"
>
</button>
`
this.viewContainerRef.clear();
const component = Component({
changeDetection: ChangeDetectionStrategy.OnPush,
template
})(class { });
const ngModule = NgModule({
imports: [
CommonModule,
BrowserModule,
BrowserAnimationsModule,
HttpClientModule,
],
entryComponents: [component],
declarations: [component]
})(class { });
this.compiler.compileModuleAndAllComponentsAsync(ngModule).then((factories) => {
const factory = factories.componentFactories[0];
const componentRef = this.viewContainerRef.createComponent(
factory,
this.viewContainerRef.length,
this.injector,
,
this.ngModuleRef
);
this.changeDetectorRef.detectChanges();
});
}
}


app.module.ts



import { NgModule, CompilerFactory, COMPILER_OPTIONS, Compiler } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { JitCompilerFactory } from '@angular/platform-browser-dynamic';

import { AppComponent } from './app.component';

export function createCompiler(compilerFactory: CompilerFactory) {
return compilerFactory.createCompiler();
}

@NgModule({
imports: [ BrowserModule, FormsModule ],
declarations: [ AppComponent ],
bootstrap: [ AppComponent ],
providers: [
{ provide: COMPILER_OPTIONS, useValue: {}, multi: true },
{ provide: CompilerFactory, useClass: JitCompilerFactory, deps: [COMPILER_OPTIONS] },
{ provide: Compiler, useFactory: createCompiler, deps: [CompilerFactory] },
],
})
export class AppModule { }


Example that does not work



Adds the MatButtonModule into the imports of the dynamic module :



app.component.ts



const ngModule = NgModule({
imports: [
CommonModule,
BrowserModule,
BrowserAnimationsModule,
HttpClientModule,
MatButtonModule,
],
entryComponents: [component],
declarations: [component]
})(class { });


Behavior



There are no errors, but the dynamic component seems to not be inserted (it is at least not visible).










share|improve this question
























  • that awkward moment a future reader looks at this and stackblitz is not available.
    – Stavm
    Nov 11 at 11:20










  • Thanks @Stavm, so I posted the code here too.
    – Hadrien TOMA
    Nov 11 at 11:21















up vote
1
down vote

favorite









up vote
1
down vote

favorite











Here are two MCVEs on StackBlitz using dynamic component creation. I would like to understand why :





  • This works.

  • But this does not work, just after importing a Material Module (MatButtonModule) into the dynamically created module.


Does anyone have an idea?



Example that works



app.component.ts



import { Component, ChangeDetectionStrategy, OnDestroy, ChangeDetectorRef, ViewChild, ViewContainerRef, Input, Compiler, Injector, NgModuleRef, SimpleChanges, NgModule, ComponentFactoryResolver, ReflectiveInjector } from '@angular/core';
import { CommonModule } from '@angular/common';
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { HttpClientModule } from '@angular/common/http';
import { MatButtonModule } from '@angular/material';

@Component({
selector: 'my-app',
template: `
<ng-container
#viewContainerRef
></ng-container>
`,
})
export class AppComponent {
@ViewChild('viewContainerRef', { read: ViewContainerRef }) viewContainerRef: ViewContainerRef;

constructor(
private compiler: Compiler,
private injector: Injector,
private ngModuleRef: NgModuleRef<any>,
private changeDetectorRef: ChangeDetectorRef,
) {
}

ngOnInit() {
const template = `
<button
mat-button
[innerHTML]="'Click me!'"
>
</button>
`
this.viewContainerRef.clear();
const component = Component({
changeDetection: ChangeDetectionStrategy.OnPush,
template
})(class { });
const ngModule = NgModule({
imports: [
CommonModule,
BrowserModule,
BrowserAnimationsModule,
HttpClientModule,
],
entryComponents: [component],
declarations: [component]
})(class { });
this.compiler.compileModuleAndAllComponentsAsync(ngModule).then((factories) => {
const factory = factories.componentFactories[0];
const componentRef = this.viewContainerRef.createComponent(
factory,
this.viewContainerRef.length,
this.injector,
,
this.ngModuleRef
);
this.changeDetectorRef.detectChanges();
});
}
}


app.module.ts



import { NgModule, CompilerFactory, COMPILER_OPTIONS, Compiler } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { JitCompilerFactory } from '@angular/platform-browser-dynamic';

import { AppComponent } from './app.component';

export function createCompiler(compilerFactory: CompilerFactory) {
return compilerFactory.createCompiler();
}

@NgModule({
imports: [ BrowserModule, FormsModule ],
declarations: [ AppComponent ],
bootstrap: [ AppComponent ],
providers: [
{ provide: COMPILER_OPTIONS, useValue: {}, multi: true },
{ provide: CompilerFactory, useClass: JitCompilerFactory, deps: [COMPILER_OPTIONS] },
{ provide: Compiler, useFactory: createCompiler, deps: [CompilerFactory] },
],
})
export class AppModule { }


Example that does not work



Adds the MatButtonModule into the imports of the dynamic module :



app.component.ts



const ngModule = NgModule({
imports: [
CommonModule,
BrowserModule,
BrowserAnimationsModule,
HttpClientModule,
MatButtonModule,
],
entryComponents: [component],
declarations: [component]
})(class { });


Behavior



There are no errors, but the dynamic component seems to not be inserted (it is at least not visible).










share|improve this question















Here are two MCVEs on StackBlitz using dynamic component creation. I would like to understand why :





  • This works.

  • But this does not work, just after importing a Material Module (MatButtonModule) into the dynamically created module.


Does anyone have an idea?



Example that works



app.component.ts



import { Component, ChangeDetectionStrategy, OnDestroy, ChangeDetectorRef, ViewChild, ViewContainerRef, Input, Compiler, Injector, NgModuleRef, SimpleChanges, NgModule, ComponentFactoryResolver, ReflectiveInjector } from '@angular/core';
import { CommonModule } from '@angular/common';
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { HttpClientModule } from '@angular/common/http';
import { MatButtonModule } from '@angular/material';

@Component({
selector: 'my-app',
template: `
<ng-container
#viewContainerRef
></ng-container>
`,
})
export class AppComponent {
@ViewChild('viewContainerRef', { read: ViewContainerRef }) viewContainerRef: ViewContainerRef;

constructor(
private compiler: Compiler,
private injector: Injector,
private ngModuleRef: NgModuleRef<any>,
private changeDetectorRef: ChangeDetectorRef,
) {
}

ngOnInit() {
const template = `
<button
mat-button
[innerHTML]="'Click me!'"
>
</button>
`
this.viewContainerRef.clear();
const component = Component({
changeDetection: ChangeDetectionStrategy.OnPush,
template
})(class { });
const ngModule = NgModule({
imports: [
CommonModule,
BrowserModule,
BrowserAnimationsModule,
HttpClientModule,
],
entryComponents: [component],
declarations: [component]
})(class { });
this.compiler.compileModuleAndAllComponentsAsync(ngModule).then((factories) => {
const factory = factories.componentFactories[0];
const componentRef = this.viewContainerRef.createComponent(
factory,
this.viewContainerRef.length,
this.injector,
,
this.ngModuleRef
);
this.changeDetectorRef.detectChanges();
});
}
}


app.module.ts



import { NgModule, CompilerFactory, COMPILER_OPTIONS, Compiler } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { JitCompilerFactory } from '@angular/platform-browser-dynamic';

import { AppComponent } from './app.component';

export function createCompiler(compilerFactory: CompilerFactory) {
return compilerFactory.createCompiler();
}

@NgModule({
imports: [ BrowserModule, FormsModule ],
declarations: [ AppComponent ],
bootstrap: [ AppComponent ],
providers: [
{ provide: COMPILER_OPTIONS, useValue: {}, multi: true },
{ provide: CompilerFactory, useClass: JitCompilerFactory, deps: [COMPILER_OPTIONS] },
{ provide: Compiler, useFactory: createCompiler, deps: [CompilerFactory] },
],
})
export class AppModule { }


Example that does not work



Adds the MatButtonModule into the imports of the dynamic module :



app.component.ts



const ngModule = NgModule({
imports: [
CommonModule,
BrowserModule,
BrowserAnimationsModule,
HttpClientModule,
MatButtonModule,
],
entryComponents: [component],
declarations: [component]
})(class { });


Behavior



There are no errors, but the dynamic component seems to not be inserted (it is at least not visible).







angular angular-material2 ng-modules






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 11 at 11:32

























asked Nov 11 at 10:22









Hadrien TOMA

7931120




7931120












  • that awkward moment a future reader looks at this and stackblitz is not available.
    – Stavm
    Nov 11 at 11:20










  • Thanks @Stavm, so I posted the code here too.
    – Hadrien TOMA
    Nov 11 at 11:21




















  • that awkward moment a future reader looks at this and stackblitz is not available.
    – Stavm
    Nov 11 at 11:20










  • Thanks @Stavm, so I posted the code here too.
    – Hadrien TOMA
    Nov 11 at 11:21


















that awkward moment a future reader looks at this and stackblitz is not available.
– Stavm
Nov 11 at 11:20




that awkward moment a future reader looks at this and stackblitz is not available.
– Stavm
Nov 11 at 11:20












Thanks @Stavm, so I posted the code here too.
– Hadrien TOMA
Nov 11 at 11:21






Thanks @Stavm, so I posted the code here too.
– Hadrien TOMA
Nov 11 at 11:21














1 Answer
1






active

oldest

votes

















up vote
3
down vote



accepted










The reason for this is that you always take the first compiled factory from array.



const factory = factories.componentFactories[0];


while you need to get the factory from your component:



const factory = factories.componentFactories.find(x => x.componentType === component);





share|improve this answer





















  • Perfect, thank you very much!
    – Hadrien TOMA
    Nov 11 at 11:45











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53247787%2fwhy-adding-a-material-module-breaks-the-dynamic-component-insertion%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes








up vote
3
down vote



accepted










The reason for this is that you always take the first compiled factory from array.



const factory = factories.componentFactories[0];


while you need to get the factory from your component:



const factory = factories.componentFactories.find(x => x.componentType === component);





share|improve this answer





















  • Perfect, thank you very much!
    – Hadrien TOMA
    Nov 11 at 11:45















up vote
3
down vote



accepted










The reason for this is that you always take the first compiled factory from array.



const factory = factories.componentFactories[0];


while you need to get the factory from your component:



const factory = factories.componentFactories.find(x => x.componentType === component);





share|improve this answer





















  • Perfect, thank you very much!
    – Hadrien TOMA
    Nov 11 at 11:45













up vote
3
down vote



accepted







up vote
3
down vote



accepted






The reason for this is that you always take the first compiled factory from array.



const factory = factories.componentFactories[0];


while you need to get the factory from your component:



const factory = factories.componentFactories.find(x => x.componentType === component);





share|improve this answer












The reason for this is that you always take the first compiled factory from array.



const factory = factories.componentFactories[0];


while you need to get the factory from your component:



const factory = factories.componentFactories.find(x => x.componentType === component);






share|improve this answer












share|improve this answer



share|improve this answer










answered Nov 11 at 11:42









yurzui

91.7k10180203




91.7k10180203












  • Perfect, thank you very much!
    – Hadrien TOMA
    Nov 11 at 11:45


















  • Perfect, thank you very much!
    – Hadrien TOMA
    Nov 11 at 11:45
















Perfect, thank you very much!
– Hadrien TOMA
Nov 11 at 11:45




Perfect, thank you very much!
– Hadrien TOMA
Nov 11 at 11:45


















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.





Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


Please pay close attention to the following guidance:


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53247787%2fwhy-adding-a-material-module-breaks-the-dynamic-component-insertion%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Full-time equivalent

Bicuculline

さくらももこ