Угловой 8 ngx-bootstrap модальный Заводской компонент не найден - PullRequest
1 голос
/ 10 июля 2019

У меня есть модуль, который выглядит примерно так:

@NgModule({
  imports: [
    EmployeeRoutingModule,
  ],
  declarations: [
    ListEmployeeComponent,
    EmployeeDialogComponent,
  ],
  providers: [
    EmployeeService,
    BsModalService,
  ],
  entryComponents: [
    EmployeeDialogComponent,
  ]
})
export class EmployeeModule {
}

И он импортируется в модуль приложения примерно так:

{
  path: 'employee',
  loadChildren: './employee/employee.module#EmployeeModule'
},

внутри app.routing.ts.

Когда я пытаюсь использовать EmployeeDialogComponent в моем EmployeeModule, он продолжает выдавать ошибку

ERROR Error: No component factory found for EmployeeDialogComponent. Did you add it to @NgModule.entryComponents?

Если я добавлю его в модуль (назовем его SharedModule) так же, какзагружается во время выполнения приложения (в файле app.module.ts) это работает.Кажется, что-то об использовании его лениво.

В чем проблема и как я могу ее решить?

Вот пример минимальной версии модального режима, которая не будет работать:

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();
  }
}

В модуле ListEmployeeComponent есть компонент, который содержит такую ​​функцию:

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) => {
      }
    );
  }
}

1 Ответ

3 голосов
/ 10 июля 2019

мне удалось воспроизвести вашу проблему в этом репо и добавление ModalModule.forRoot() к EmployeeModule импортам исправит ошибку.

У меня была похожая проблема с MatDialog, напримерчто, когда я хотел использовать компонент из лениво загруженного модуля в уже созданном экземпляре MatDialog (который является инъекционным), я получал ту же ошибку.Тогда я заметил, что сервис должен быть инициализирован с нуля, когда он будет использоваться с лениво загруженными компонентами.И нечто подобное происходит и в вашем случае.

в соответствии с документами ModalModule импортируется с forRoot() подобно;

// RECOMMENDED
import { ModalModule } from 'ngx-bootstrap/modal';
// or
import { ModalModule } from 'ngx-bootstrap';

@NgModule({
  imports: [ModalModule.forRoot(),...]
})
export class AppModule(){}

, что означает, что глобальный единый экземпляр BsModalService создается и используется ввсе приложение.И он не имеет никаких знаний о лениво загруженных компонентах при инициализации.

Таким образом, решение будет состоять в том, чтобы инициализировать новый экземпляр для лениво загруженного модуля, так что добавление ModalModule.forRoot() к EmployeeModule импортам исправитошибка.

@NgModule({
  imports: [
    EmployeeRoutingModule,
    ModalModule.forRoot()
  ],
  declarations: [
    EmployeeDialogComponent,
    ListEmployeeComponent,
  ],
  providers: [
    BsModalService,
  ],
  entryComponents: [
    EmployeeDialogComponent,
  ]
})
export class EmployeeModule {}

однако имейте в виду, что это создаст новый экземпляр BsModalService, выделенный для EmployeeModule, и он не будет знать ни о каком другом контексте вне его, а также о каком-либо внешнемконтекст не будет знать об этом.что в более простых терминах означает, что вы не можете взаимодействовать с этим конкретным диалогом (например, закрывать его) где-либо еще, кроме EmployeeModule context.

...