[英]Angular 2 (Final): resetConfig to add routes to lazy loaded routes
I'm trying to understand how to dynamically add routes to those from a lazy loaded module. 我试图了解如何动态添加路由到延迟加载模块的路由。 I have the core app, with routes:
我有核心应用程序,有路线:
export const routes = [{
path: "",
component: HomeComponent
}, {
path: "moduleA",
loadChildren: "app/moduleA/A.module"
}];
In A.module I import routes from the "local" moduleA.routes.config.ts: 在A.module中,我从“local”moduleA.routes.config.ts导入路由:
const routes = [{
path: "",
component: ModuleAHomeComponent,
children: [
{ path: "", component: ModuleAListComponent },
{ path: ":id", component: ModuleADetailComponent }
]
}];
export const routing = RouterModule.forChild(routes);
So far so good. 到现在为止还挺好。 Now, in ModuleADetailComponent I have a list of "additional modules", which I'll call plugins, for my webapp, which are developed separately and I want to be able to show in ModuleADetailComponent page.
现在,在ModuleADetailComponent中,我有一个“附加模块”列表,我将其称为插件,用于我的webapp,它们是单独开发的,我希望能够在ModuleADetailComponent页面中显示。 Therefore, the template for this component is something like this:
因此,此组件的模板是这样的:
<div *ngFor="let plugin of plugins">
<div class="header">{{ plugin.name }}</div>
<router-outlet name="*plugin.name*">*LOAD MODULE HERE*</router-outlet>
</div>
Of course, plugins is a configuration loaded upon navigation to ModuleADetailComponent, so I don't know ahead of time which modules are configured and how many there are. 当然,插件是导航到ModuleADetailComponent时加载的配置,所以我不知道提前配置了哪些模块以及有多少模块。 Lastly, each of these plugins can be an NgModule (developed separately in a workbench environment).
最后,这些插件中的每一个都可以是NgModule(在工作台环境中单独开发)。
What I need is: how do I modify the router configuration, dynamically, to add children to the route defined in moduleA.routes.config.ts? 我需要的是:如何动态修改路由器配置,将子节点添加到moduleA.routes.config.ts中定义的路由? For example, if I have 2 plugins, I want to dynamically use router.resetConfig to have what I would have if moduleA.routes.config.ts was like this:
例如,如果我有2个插件,我想动态使用router.resetConfig,如果moduleA.routes.config.ts是这样的话,我将拥有它:
const routes = [{
path: "",
component: ModuleAHomeComponent,
children: [
{ path: "", component: ModuleAListComponent },
{
path: ":id",
component: ModuleADetailComponent,
children: [
{
path: "plugin1",
loadChildren: "app/plugins/plugin1.module",
outlet: "plugin1"
},
{
path: "plugin2",
loadChildren: "app/plugins/plugin2.module",
outlet: "plugin2"
}
]
}
]
}];
export const routing = RouterModule.forChild(routes);
I hope I can achieve it, otherwise plugins will have to be developed without routing...but they can become big sub-modules which would benefit from navigation. 我希望我能实现它,否则插件必须在没有路由的情况下开发......但它们可以成为可以从导航中受益的大型子模块。
EDIT 27/09/2016 : I've assembled this plunkr: http://plnkr.co/edit/6aV5n5K5wdqdiYo49lZv . 编辑27/09/2016 :我已经组装了这个plunkr: http ://plnkr.co/edit/6aV5n5K5wdqdiYo49lZv。 What I am currently able to do is load components dynamically and add them to the application (see tab "Dynamic Modules").
我目前能够做的是动态加载组件并将它们添加到应用程序(请参见“动态模块”选项卡)。 What I've also done is to use multiple named router-outlets, despite not finding any official documentation (see tab "Dynamic Routed").
我还做的是使用多个命名路由器插座,尽管没有找到任何官方文档(请参阅“动态路由”选项卡)。 Despite the tab name, routes are known ahead of time.
尽管标签名称,但路线是提前知道的。
What I want to do is: dynamically load a configuration (the dynamicRoutes array in the DynamicRoutesComponent) and only after create one router-outlet per dynamic route and use resetConfig (or what it takes) to have this configuration: 我想要做的是:动态加载一个配置(DynamicRoutesComponent中的dynamicRoutes数组),并且只在每个动态路由创建一个路由器出口并使用resetConfig(或它需要什么)来进行此配置:
{
path: "dynamic-routed",
component: DynamicRoutesComponent,
children: [
{ path: "", component: EmptyComponent },
{ path: "component1", component: Component1, outlet: "component1" },
{ path: "component2", component: Component2, outlet: "component2" }
]
}
with one child per dynamic route. 每个动态路线有一个孩子。
Thanks in advance! 提前致谢!
First of all, the loadChildren
property method must be supplied with the following format ( https://angular.io/docs/ts/latest/guide/router.html#!#asynchronous-routing ): 首先,必须使用以下格式提供
loadChildren
属性方法( https://angular.io/docs/ts/latest/guide/router.html#!#asynchronous-routing ):
{
path: 'admin',
loadChildren: 'app/admin/admin.module#AdminModule',
},
As you see above, the module path
and the module name
are joined with the #
char. 正如你看到的上面的
module path
和module name
都加入与#
字符。
In your case, you need to to modify your app.routes more or less as follows (not sure about your module/file names, and the plunkr sample does not reflect the names given in this question): 在您的情况下,您需要或多或少地修改您的app.routes如下(不确定您的模块/文件名,并且plunkr示例不反映此问题中给出的名称):
export const routes = [{
path: "",
component: HomeComponent
}, {
path: "moduleA",
loadChildren: "app/moduleA#ModuleA"
}];
This was just an intro, now let's proceed to the solution of your problem. 这只是一个介绍,现在让我们继续解决您的问题。 As far as I read, you want to dynamically add child routes.
据我所知,您想要动态添加子路由。
You can dynamically provide child routes in your feature module by using the following code. 您可以使用以下代码在功能模块中动态提供子路由。
import {ROUTES} from '@angular/router/src/router_config_loader';
import {ANALYZE_FOR_ENTRY_COMPONENTS} from '@angular/core';
[...]
let routesToAdd = ... // provide your routes here
@NgModule({
[...]
imports: [RouterModule.forChild([])] // Empty on purpose
[...]
providers: [
{
provide: ROUTES,
useValue: routesToAdd,
multi: true
},
{
provide: ANALYZE_FOR_ENTRY_COMPONENTS,
useValue: routesToAdd, // provide them here too
multi: true
}
],
[...]
})
You had to provide same routes for ANALYZE_FOR_ENTRY_COMPONENTS
token (as well as ROUTES
token) otherwise you'll get the No component factory found for YOUR_COMPONENT. Did you add it to @NgModule.entryComponents?
您必须为
ANALYZE_FOR_ENTRY_COMPONENTS
令牌(以及ROUTES
令牌)提供相同的路由,否则您将获得No component factory found for YOUR_COMPONENT. Did you add it to @NgModule.entryComponents?
的No component factory found for YOUR_COMPONENT. Did you add it to @NgModule.entryComponents?
No component factory found for YOUR_COMPONENT. Did you add it to @NgModule.entryComponents?
error. 错误。
However, this code might produce errors during AoT compilation. 但是,此代码可能会在AoT编译期间产生错误。 In this case, you'll need to provide a
factory
instead of a value
for ROUTES
token. 在这种情况下,您需要提供
factory
而不是ROUTES
令牌的value
。 However, you won't be able to provide a factory
for ANALYZE_FOR_ENTRY_COMPONENTS
token - it does only accept useValue
(see https://github.com/angular/angular/blob/03e855ae8f9e9b86251320c7551a96092bd8b0c4/modules/%40angular/compiler/src/metadata_resolver.ts#L926 ). 但是,您将无法为
ANALYZE_FOR_ENTRY_COMPONENTS
令牌提供factory
- 它只接受useValue
(请参阅https://github.com/angular/angular/blob/03e855ae8f9e9b86251320c7551a96092bd8b0c4/modules/%40angular/compiler/src/metadata_resolver。 ts#L926 )。
In that case, use the following code on your feature module: 在这种情况下,请在功能模块上使用以下代码:
import {ROUTES} from '@angular/router/src/router_config_loader';
[...]
let routesToAdd = ... // provide your routes here
@NgModule({
[...]
imports: [RouterModule.forChild([])] // Empty on purpose
[...]
providers: [
{
provide: ROUTES,
useFactory: (getRoutesFromSomewhere),
//deps: [SomeService, SOME_TOKEN] // deps is optional, in the case you need no params - delete it; otherwise pass 'em
multi: true
}
],
entryComponents: [CompA, CompB, CompC, etc...]
[...]
})
Note : Using Observables/Promises to provide routes is not a reliable solution, hence the Angular router expects Route[]
or Routes
, but an HTTP request can only return an Observable/Promise (The Angular app gets initialized, but the retrieval process of routes still goes on using Observables/Promises) (see https://github.com/ngx-i18n-router/config-loader#readme ). 注意 :使用Observables / Promises提供路由不是一个可靠的解决方案,因此Angular路由器需要
Route[]
或Routes
,但HTTP请求只能返回Observable / Promise(Angular应用程序被初始化,但路由的检索过程)仍然继续使用Observables / Promises)(参见https://github.com/ngx-i18n-router/config-loader#readme )。
Use such functions which return Route[]
or Routes
. 使用返回
Route[]
或Routes
函数。
Meantime, you might check the module file of @ngx-i18n-router/core (an internationalization utility for Angular, benefits from dynamic routes) and this example-app as its implentation. 同时,您可以检查@ ngx-i18n-router / core的模块文件 (Angular的国际化实用程序,从动态路由中获益)以及此example-app作为其实现。
Would it be possible to do something like this ? 是否有可能做这样的事情这样 ? Basically, in the constructor of a component you have access to
activatedRoute.routeConfig.children
, with which you should be able to add more children to that array. 基本上,在组件的构造函数中,您可以访问
activatedRoute.routeConfig.children
,您应该可以使用该元素向该数组添加更多子项。
If you are trying to get data from another source, you should be able to set this up in the subscriber
part of an Observable
. 如果您尝试从其他源获取数据,则应该能够在
Observable
的subscriber
部分中进行设置。 I'm thinking something like this: 我在想这样的事情:
@Component({
selector: 'app-module-a-detail',
templateUrl: './module-a-detail.component.html'
})
export class ModuleADetailComponent {
constructor(
private activatedRoute: ActivatedRoute) {
const childRoutes: Routes = this.activatedRoute.routeConfig.children;
this.pluginService.getPlugins({
.subscribe(map(plugin => {
// build up my additional childRoute here
childRoutes.push(newChildRoute);
}))
);
}
}
Actually the problem to me is how costructing newChildRoute
: 实际上我遇到的问题是如何构建
newChildRoute
:
before I had something like: 在我之前有这样的事情:
"path": pathFromFile,
"outlet": outletFromFile,
"data": dataFromFile,
"component": HostComponent, (my custom host component for named outlet)
"loadChildren": moduleURLFromFile + "#" + moduleNameFromFile
to create new objects {} to change my actual this.router.config
. 创建新对象{}来改变我的实际
this.router.config
。
in this way calling this.router.resetConfig(this.router.config);
以这种方式调用
this.router.resetConfig(this.router.config);
should work.... 应该管用....
but replacing "loadChildren": moduleURLFromFile + "#" + moduleNameFromFile 但是替换“loadChildren”:moduleURLFromFile +“#”+ moduleNameFromFile
with 同
"loadChildren": () => import(moduleURLFromFile ).then(m => m.moduleNameFromFile) “loadChildren”:()=> import(moduleURLFromFile).then(m => m.moduleNameFromFile)
seems not working. 似乎不起作用。
hope this better clarify 希望这更好地澄清
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.