I have a module which looks something like:
@NgModule({
imports: [
EmployeeRoutingModule,
],
declarations: [
ListEmployeeComponent,
EmployeeDialogComponent,
],
providers: [
EmployeeService,
BsModalService,
],
entryComponents: [
EmployeeDialogComponent,
]
})
export class EmployeeModule {
}
And it is imported into the app module like so
{
path: 'employee',
loadChildren: './employee/employee.module#EmployeeModule'
},
within the app.routing.ts
.
When I try and use EmployeeDialogComponent
in my EmployeeModule
it keeps giving off the error
ERROR Error: No component factory found for EmployeeDialogComponent. Did you add it to @NgModule.entryComponents?
If I add it to a module (let's call it SharedModule
) the same way that is loaded at app run time (in the app.module.ts
file) it works. It seems to be something about using it lazily.
What is the problem and how can I solve it?
Here is an example of minimal version of a modal that won't work:
import {Component, EventEmitter, OnInit, Output} from '@angular/core';
import {BsModalRef} from 'ngx-bootstrap';
@Component({
selector: 'modal-content',
template: `
<div class="modal-body text-center">
<p class="lead mb-5">{{ message }}</p>
<button type="button" class="btn btn-lg btn-outline-secondary mr-5" (click)="decline()" >{{ btnNoText }}</button>
<button type="button" class="btn btn-lg btn-success" (click)="confirm()" >{{ btnYesText }}</button>
</div>
`
})
export class ConfirmEmployeeModalComponent implements OnInit {
@Output() result = new EventEmitter<boolean>();
message = 'Are you sure?';
btnNoText = 'No';
btnYesText = 'Yes';
constructor(public bsModalRef: BsModalRef) {
}
ngOnInit() {}
confirm(): void {
this.result.emit(true);
this.bsModalRef.hide();
}
decline(): void {
this.result.emit(false);
this.bsModalRef.hide();
}
}
I have a component within the module ListEmployeeComponent
which contains a function like so:
import {
Component,
NgZone,
ElementRef,
OnInit,
ViewContainerRef,
PipeTransform,
Pipe,
ViewChild
} from '@angular/core';
import {FormControl} from '@angular/forms';
import {DialogService, BuiltInOptions} from "ngx-bootstrap-modal";
//import { EmployeeDialogComponent } from '../employee-dialog/employee-dialog.component';
import {EmployeeService} from "../employee.service";
import {LocalStorageUtilityService, NotificationService} from "../../common/common.services";
import * as _ from 'lodash';
//import { NotifyDialogComponent } from '../../common/dialog/notify-dialog/notify-dialog.component';
import {UserService} from "../../common/user.service";
import {ConfirmModalComponent} from "../../common/confirm-modal/confirm-modal.component";
import {BsModalService} from "ngx-bootstrap/modal";
import {EmployeeDialogComponent} from "../employee-dialog/employee-dialog.component";
import {ConfirmEmployeeModalComponent} from "../confirm-employee-modal/confirm-modal.component";
@Component({
templateUrl: 'list-employee.component.html',
styleUrls: ['./list-employee.component.css']
})
export class ListEmployeeComponent {
constructor(
private modalService: BsModalService,
public _dialogService: DialogService,
public _companyService: EmployeeService,
public _notificationService: NotificationService,
private userService: UserService,
) {
}
showAddEmployeeDialog = () => {
this.modalService.show(ConfirmEmployeeModalComponent, {}).content.result.subscribe((details: any) => {
}
);
}
}
i managed to reproduce your issue in this repo and adding ModalModule.forRoot()
to EmployeeModule
imports will fixes the error.
i had a similar problem with MatDialog
, such that when i wanted to use a component from a lazy loaded module in an already created instance of MatDialog
(which is an injectable) i was getting the same error. Then i noticed that the service should be initialized from scratch when to be used with lazy-loaded components. And something similar is happening in your case as well.
according to docs ModalModule
is imported with forRoot()
like;
// RECOMMENDED
import { ModalModule } from 'ngx-bootstrap/modal';
// or
import { ModalModule } from 'ngx-bootstrap';
@NgModule({
imports: [ModalModule.forRoot(),...]
})
export class AppModule(){}
which means a global singleton instance of BsModalService
is created and used across whole app. And it doesn't have any knowledge of lazy-loaded components at initialization.
So, solution would be to initialize a new instance for lazy-loaded module such that adding ModalModule.forRoot()
to EmployeeModule
imports will fix the error.
@NgModule({
imports: [
EmployeeRoutingModule,
ModalModule.forRoot()
],
declarations: [
EmployeeDialogComponent,
ListEmployeeComponent,
],
providers: [
BsModalService,
],
entryComponents: [
EmployeeDialogComponent,
]
})
export class EmployeeModule {}
however be aware that this will create a new instance of BsModalService
dedicated to EmployeeModule
and it won't be aware of any other context outside of it as well as any outside context won't be aware of it. which in simpler terms means you can't interact with this particular dialog (such as closing it) anywhere else except EmployeeModule
context.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With