如何从 NgbModal 中的延迟加载模块中打开组件?

Posted

技术标签:

【中文标题】如何从 NgbModal 中的延迟加载模块中打开组件?【英文标题】:How to open a component from lazy loaded module in NgbModal? 【发布时间】:2018-06-15 23:46:41 【问题描述】:

我在尝试从延迟加载的模块加载动态组件时遇到问题。更准确地说,我试图在模式 (https://ng-bootstrap.github.io/#/components/modal/examples) 中打开登录组件,而不是在单独的页面中,同时保持单独的登录路径/页面完整。

现在,在我看来,一个选项是我必须急切地在应用程序模块中加载登录组件,这只不过是一种临时破解。所以,我不想要这个解决方案。

我曾尝试直接使用该组件,但正如我所料,它给了我以下错误:

未找到 SigninComponent 的组件工厂。你把它添加到@NgModule.entryComponents 了吗?

我搜索并找到了此链接:https://github.com/angular/angular/issues/14324,但无法使用。

我很惊讶我找不到合适的解决方案来解决这个问题,因为这是一个非常常见的用例。任何帮助或建议表示赞赏。谢谢!

【问题讨论】:

你能提供最小的复制吗? 【参考方案1】:

没有通过选择器直接在模板中使用的组件必须添加到 @NgModule 装饰器中模块的 entryComponents 数组中。在引导程序中打开模式时,您实际上并没有在任何地方使用组件的选择器,因此您的 SignInComponent 就是这样一个示例。

你会做这样的事情

@NgModule(
    //...
    declarations: [
        SignInComponent,
    ],
    entryComponents: [
        SignInComponent,
    ]
)
export class LazyLoadedModule 

标记要编译的组件,即使它没有通过其选择器在任何其他组件的模板中引用。

您可以在官方 Angular 文档here 中阅读有关入口组件、它们如何工作以及为什么需要以这种方式声明它们的更多信息。以及这个 *** post。

【讨论】:

【参考方案2】:

这就是我设法做你想做的事的方法。这个想法是,由于登录组件位于惰性模块中,由于在导航到某些路由时路由器会加载惰性模块,因此您需要在模式内部导航到加载惰性模块并显示登录名的路由零件。这可以使用命名的路由器插座来完成。我对命名路由器插座不是很有经验,所以可能有一些需要改进的地方,但它似乎有效。

因此,假设您有一个惰性模块 LoginModule,其中包含一个显示登录组件的空路径路由,下面是如何定义根模块的路由:

export const ROUTES: Routes = [
  
    path: '',
    component: HomeComponent
  ,
  
    path: 'login', 
    loadChildren: './login/login.module#LoginModule'
  ,
   
    path: 'modal-login',
    component: ModalLoginShellComponent, 
    outlet: 'modal', 
    children: [
       
         path: '',
         loadChildren: './login/login.module#LoginModule'
       
    ]
  
];

home 组件将有一个链接,允许在 modal 中打开 ModalLoginComponent(如 ng-bootstrap 示例所示)。这个 ModalLoginComponent 模板看起来像这样:

<div class="modal-header">
  <h4 class="modal-title">Hi there!</h4>
  <button type="button" class="close" aria-label="Close" (click)="activeModal.dismiss('Cross click')">
    <span aria-hidden="true">&times;</span>
  </button>
</div>
<div class="modal-body">
  <router-outlet name="modal"></router-outlet>
</div>
<div class="modal-footer">
  <button type="button" class="btn btn-outline-dark" (click)="activeModal.close('Close click')">Close</button>
</div>

重要的部分是

<router-outlet name="modal"></router-outlet>

它允许在模态框内导航到一个路由,尤其是一个会加载惰性模块的路由。

ModalLoginComponent 的代码将具有以下 ngOnInit(),它将触发导航:

ngOnInit() 
  this.router.navigate([outlets: 'modal': ['modal-login']]);

这将因此加载 ModalLoginShellComponent 及其在模态主体内的默认延迟加载子路由。 ModalLoginShellComponent 是一个愚蠢的组件,什么都不做,只是将其作为模板

<router-outlet></router-outlet>

【讨论】:

我已经尝试过了,它有效。但我仍然相信必须有更好的解决方案。我会接受答案,但我认为我必须急切地加载登录和注册组件以避免这种混乱。非常感谢您的回答!

以上是关于如何从 NgbModal 中的延迟加载模块中打开组件?的主要内容,如果未能解决你的问题,请参考以下文章

React 中的延迟加载 util 函数

如何检查 Angular 模块延迟加载是不是适用于 Chrome?

没有路由器的角度延迟加载模块

延迟加载模块中的角度延迟加载模块

延迟加载模块中的 Angular single-spa 延迟加载路由调用未定义的 webpack 错误

日期选择器隐藏在 ag-grid-angular 中,在 NgbModal 中加载