[英]Angular 2 sub apps, parent/child, nested components, nested router-outlet, design/coding
我有一个Angular 2应用程序。 主屏幕(app?)看起来像这样......
当您单击顶部菜单routerLinks中的项目时,新组件将加载到主视图路由器插座中。 其中一个链接加载一个新的“管理”模块/组件,它有自己的路由和新的路由器插座......
然后当您单击左侧导航栏中的routerLinks时,新的管理组件将加载到新的路由器插座中。
但...
Angular 2不允许超过1个路由器插座。 因此,单击左侧导航栏中的任何routerLink只会替换整个初始路由器插座视图。
我已经看到使用“bootstrap”加载后续组件的一些SO帖子(更旧,可能已弃用),但我无法让它工作。 我甚至无法import { bootstrap } from 'anywhere at all, nothing works'
。 所以也许这不是这样做的方式。
如何让Admin子应用程序部分工作?
非常非常感谢您分享您的Angular 2专业知识:-)
编辑:尝试以下建议的解决方案。 无论我把路由放在哪里,在基础app.routes.ts或子应用程序admin.routes.ts中,无论我如何格式化routerLinks,我都会收到此错误...
再次编辑:这是路由器和模板中的代码......
<!--
============================================================================
/src/app/component/admin/admin.component.html
-->
<!-- Row for entire page columnar dispaly -->
<div class="row">
<!-- Column 1: Left navigation, links to all admin components -->
<div class="col col-md-4">
<app-admin-nav></app-admin-nav>
</div>
<!-- Column 2: Rows of records, click to edit -->
<div class="col col-md-8">
<router-outlet name="admin-app"></router-outlet>
</div>
</div>
// ============================================================================
// /src/app/app.routes.ts
import { ModuleWithProviders } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { AppComponent } from './app.component';
import { GameComponent } from './component/game/game.component';
import { HomeComponent } from './component/home/home.component';
import { LoginComponent } from './component/login/login.component';
import { PlayerComponent } from './component/player/player.component';
import { AuthGuard } from './service/auth/auth.service';
import { SignupComponent } from './component/signup/signup.component';
import { EmailComponent } from './component/email/email.component';
import { AdminComponent } from './component/admin/admin.component';
// import { AdminWorldComponent } from './component/admin/world/admin-world.component';
// import { AdminModuleComponent } from './component/admin/module/admin-module.component';
// import { AdminRegionComponent } from './component/admin/region/admin-region.component';
export const router: Routes = [
{ path: '', redirectTo: 'home', pathMatch: 'full' }
, { path: 'home', component: HomeComponent }
, { path: 'game', component: GameComponent, canActivate: [AuthGuard] }
, { path: 'admin', component: AdminComponent, canActivate: [AuthGuard] }
// , {
// path: 'admin', component: AdminComponent, canActivate: [AuthGuard],
// children: [
// { path: 'world', component: AdminWorldComponent, outlet: 'admin-app' },
// { path: 'module', component: AdminModuleComponent, outlet: 'admin-app' },
// { path: 'region', component: AdminRegionComponent, outlet: 'admin-app' }
// ]
// },
, { path: 'login', component: LoginComponent }
, { path: 'signup', component: SignupComponent }
, { path: 'login-email', component: EmailComponent }
, { path: 'players', component: PlayerComponent, canActivate: [AuthGuard] }
];
export const routes: ModuleWithProviders = RouterModule.forRoot(router);
// ============================================================================
// /src/app/component/admin/admin.routes.ts
import { ModuleWithProviders } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { AdminComponent } from './admin.component';
import { AdminWorldComponent } from './world/admin-world.component';
import { AdminModuleComponent } from './module/admin-module.component';
import { AdminRegionComponent } from './region/admin-region.component';
export const router: Routes = [
{
path: 'admin', component: AdminComponent,
children: [
{ path: 'world', component: AdminWorldComponent, outlet: 'admin-app' }
, { path: 'module', component: AdminModuleComponent, outlet: 'admin-app' }
, { path: 'region', component: AdminRegionComponent, outlet: 'admin-app' }
]
}
];
export const routes: ModuleWithProviders = RouterModule.forRoot(router);
编辑3:尝试将RouterModule.forRoot
更改为RouterModule.forChild
,遗憾的是,同样的错误: - /
编辑4:转换路由以使用2个路由模块。 希望可能会有所作为,但同样的错误。
新路由器......
// ============================================================================
// /src/app/app-routing.module.ts
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { AppComponent } from './app.component';
import { GameComponent } from './component/game/game.component';
import { HomeComponent } from './component/home/home.component';
import { LoginComponent } from './component/login/login.component';
import { PlayerComponent } from './component/player/player.component';
import { AuthGuard } from './service/auth/auth.service';
import { SignupComponent } from './component/signup/signup.component';
import { EmailComponent } from './component/email/email.component';
import { AdminComponent } from './component/admin/admin.component';
export const appRoutes: Routes = [
{ path: '', redirectTo: 'home', pathMatch: 'full' }
, { path: 'home', component: HomeComponent }
, { path: 'game', component: GameComponent, canActivate: [AuthGuard] }
, { path: 'admin', component: AdminComponent, canActivate: [AuthGuard] }
// , {
// path: 'admin', component: AdminComponent, canActivate: [AuthGuard],
// children: [
// { path: 'world', component: AdminWorldComponent, outlet: 'admin-app' },
// { path: 'module', component: AdminModuleComponent, outlet: 'admin-app' },
// { path: 'region', component: AdminRegionComponent, outlet: 'admin-app' }
// ]
// },
, { path: 'login', component: LoginComponent }
, { path: 'signup', component: SignupComponent }
, { path: 'login-email', component: EmailComponent }
, { path: 'players', component: PlayerComponent, canActivate: [AuthGuard] }
];
@NgModule({
imports: [
RouterModule.forRoot(appRoutes)
],
exports: [
RouterModule
]
})
export class AppRoutingModule { }
// ============================================================================
// /src/app/admin/admin-routing.module.ts
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { AdminComponent } from './admin.component';
import { AdminWorldComponent } from './world/admin-world.component';
import { AdminModuleComponent } from './module/admin-module.component';
import { AdminRegionComponent } from './region/admin-region.component';
export const adminRoutes: Routes = [
{
path: 'admin', component: AdminComponent,
children: [
{ path: 'world', component: AdminWorldComponent, outlet: 'admin-app' }
, { path: 'module', component: AdminModuleComponent, outlet: 'admin-app' }
, { path: 'region', component: AdminRegionComponent, outlet: 'admin-app' }
]
}
];
@NgModule({
imports: [
RouterModule.forChild(adminRoutes)
],
exports: [
RouterModule
]
})
export class AdminRoutingModule { }
编辑5:它正在工作!
删除了路由模块,根据Tyler的建议返回到导出路由配置。 他是对的,路由模块不能正常工作。 泰勒和我一起工作很多,所以我接受了他的回答。 谢谢泰勒的帮助!
以下是如何使用自己的路由器插座设置父应用程序,然后在父级单击链接以使用自己的新路由器插件加载子应用程序。 子应用程序加载/替换父应用程序路由器插座。
父app模块或路由中没有什么特别之处。 他们就是我在这篇文章之前的方式。
需要注意的重要事项 ,至少在我今天的情况下, 不要在子路由器插座中使用name=""
attrib。 这将导致“错误:无法匹配任何路线......”。 不要像我上面尝试的那样使用路由模块,这也会导致“错误:无法匹配任何路由......”。 不要在路由中使用outlet: 'blah'
,这也会导致“错误:无法匹配任何路由......”。 确保设置子路由配置children: []
完全如下面admin.routes.ts中所示。 另请注意RouterModule.forChild(router)
。 这些事情为我今天解决了这个问题。
家长APP
// ============================================================================
// src/app/app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';
import { AngularFireModule } from 'angularfire2';
import { firebaseConfig } from '../environments/firebase.config';
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
// import { AppRoutingModule } from './app-routing.module';
import { routes } from './app.routes';
// Components
import { AppComponent } from './app.component';
import { HomeComponent } from './component/home/home.component';
import { GameComponent } from './component/game/game.component';
import { PlayerComponent } from './component/player/player.component';
import { LoginComponent } from './component/login/login.component';
import { SignupComponent } from './component/signup/signup.component';
import { EmailComponent } from './component/email/email.component';
// Admin Module
import { AdminModule } from './component/admin/admin.module';
// Services
import { AuthGuard } from './service/auth/auth.service';
import { AuthPlayerService } from './service/auth/auth-player.service';
import { MdbService } from './service/mongo/mdb.service';
import { PlayerMdbService } from './service/mongo/player-mdb.service';
@NgModule({
declarations: [
AppComponent
, HomeComponent
, GameComponent
, PlayerComponent
, LoginComponent
, SignupComponent
, EmailComponent
],
imports: [
BrowserModule
, FormsModule
, HttpModule
, AdminModule
, AngularFireModule.initializeApp(firebaseConfig)
, NgbModule.forRoot()
// , AppRoutingModule
, routes
],
providers: [
AuthGuard
, AuthPlayerService
, MdbService
, PlayerMdbService
],
bootstrap: [AppComponent]
})
export class AppModule { }
// ============================================================================
// /src/app/app.routes.ts
import { ModuleWithProviders } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { AppComponent } from './app.component';
import { GameComponent } from './component/game/game.component';
import { HomeComponent } from './component/home/home.component';
import { LoginComponent } from './component/login/login.component';
import { PlayerComponent } from './component/player/player.component';
import { AuthGuard } from './service/auth/auth.service';
import { SignupComponent } from './component/signup/signup.component';
import { EmailComponent } from './component/email/email.component';
import { AdminComponent } from './component/admin/admin.component';
export const router: Routes = [
{ path: '', redirectTo: 'home', pathMatch: 'full' },
{ path: 'home', component: HomeComponent },
{ path: 'game', component: GameComponent, canActivate: [AuthGuard] },
{ path: 'admin', component: AdminComponent, canActivate: [AuthGuard] },
{ path: 'login', component: LoginComponent },
{ path: 'signup', component: SignupComponent },
{ path: 'login-email', component: EmailComponent },
{ path: 'players', component: PlayerComponent, canActivate: [AuthGuard] }
];
export const routes: ModuleWithProviders = RouterModule.forRoot(router);
儿童APP
// ============================================================================
// /src/app/admin/admin.module.ts
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { CommonModule } from '@angular/common';
import { routes } from './admin.routes';
// import { AdminRoutingModule } from './admin-routing.module';
import { AdminComponent } from './admin.component';
import { AdminRecsComponent } from './admin-recs.component';
import { AdminFormComponent } from './admin-form.component';
import { AdminNavComponent } from './admin-nav.component';
import { AdminWorldComponent } from './world/admin-world.component';
import { AdminModuleComponent } from './module/admin-module.component';
import { AdminRegionComponent } from './region/admin-region.component';
@NgModule({
imports: [
CommonModule
, FormsModule
// , AdminRoutingModule
, routes
]
, declarations: [
AdminComponent
, AdminNavComponent
, AdminRecsComponent
, AdminFormComponent
, AdminWorldComponent
, AdminModuleComponent
, AdminRegionComponent
]
, schemas: [CUSTOM_ELEMENTS_SCHEMA]
, exports: [
AdminRecsComponent
, AdminFormComponent
, AdminNavComponent
// , AdminWorldComponent
// , AdminModuleComponent
// , AdminRegionComponent
]
// , bootstrap: [AdminComponent]
})
export class AdminModule { }
// ============================================================================
// /scr/app/admin/admin.routes.ts
import { ModuleWithProviders } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { AdminComponent } from './admin.component';
import { AdminWorldComponent } from './world/admin-world.component';
import { AdminModuleComponent } from './module/admin-module.component';
import { AdminRegionComponent } from './region/admin-region.component';
export const router: Routes = [
{
path: 'admin', component: AdminComponent,
children: [
{ path: 'world', component: AdminWorldComponent },
{ path: 'module', component: AdminModuleComponent },
{ path: 'region', component: AdminRegionComponent },
]
}
];
export const routes: ModuleWithProviders = RouterModule.forChild(router);
不知道你在哪里听说Angular2不允许超过1个router-outlet
。 我在一个大型应用程序中使用了几个。
您的主app.component将有一个router-outlet
来处理根路由。 如果您的某个路由延迟加载管理模块,该管理模块将拥有其根组件,其中包含侧面菜单栏和所有子路由的router-outlet
。
例:
//app.routes
export const ROUTES: Routes = [
// Main redirect
{ path: '', component: MainViewComponent },
{
path: 'admin',
loadChildren: './admin/admin.module#AdminModule'
}
]
您的MainViewComponent可以包含顶部导航栏和router-outlet
。
然后Admin路由器配置可能如下所示:
export const routes: Routes = [
{
path: '',
component: AdminComponent,
children: [
{ path: '', component: Component1},
{ path: 'component2', component: Component2}
]
}
];
管理模块中的根组件可能包含侧栏菜单和router-outlet
用于显示子组件。
您也可以做命名的router-outlets
。 这方面的一个例子是并排放置两个router-outlet
:
<router-outlet></router-outlet>
<router-outlet name="popup"></router-outlet>
您的路由器配置如下所示:
{
path: 'compose',
component: ComposeMessageComponent,
outlet: 'popup'
},
你会像这样使用它:
<a [routerLink]="[{ outlets: { popup: ['compose'] } }]">Contact</a>
或者用以下内容清除内容:
this.router.navigate([{ outlets: { popup: null }}]);
希望有所帮助。
编辑
为延迟加载的子项使用路由配置时,请确保在模块中正确加载路由配置。 根路由配置将在带有RouterModule.forRoot(routes)
的根AppModule中加载,子路由在带有RouterModule.forChild(routes)
的子模块中。
您的路由配置和模块需要如下所示(不要创建一个单独的模块来保存路由配置):
//管理员路线
export const adminRoutes: Routes = [
{
path: 'admin', component: AdminComponent,
children: [
{ path: 'world', component: AdminWorldComponent, outlet: 'admin-app' }
, { path: 'module', component: AdminModuleComponent, outlet: 'admin-app' }
, { path: 'region', component: AdminRegionComponent, outlet: 'admin-app' }
]
}
];
//管理模块:
import { adminRoutes } from './admin.routes';
@NgModule({
imports: [
...
RouterModule.forChild(adminRoutes),
]
...
// App Routes(延迟加载管理模块)
export const appRoutes: Routes = [
{ path: 'admin', loadChildren: './admin/admin.module#AdminModule' },
....
//应用模块
import { appRoutes } from './app.routes';
@NgModule({
imports: [
...
RouterModule.forRoot(appRoutes),
]
...
希望有所帮助。
是的,有办法做到这一点。 您需要将路由器插座命名为:
<router-outlet name="child1"></router-outlet>
<router-outlet name="child2"></router-outlet>
在路由器内部,您需要定义路由器应该路由使用的路由器:
{
path: 'home', // you can keep it empty if you do not want /home
component: 'appComponent',
children: [
{
path: '',
component: childOneComponent,
outlet: 'child1'
},
{
path: '',
component: childTwoComponent,
outlet: 'child2'
}
]
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.