【发布时间】:2016-08-04 09:20:47
【问题描述】:
上下文
我正在使用 Angular 2、TypeScript、@ngrx/store 和 SystemJS 开发一个项目。我已经构建了一个模块加载器,因此我可以通过组装模块来构建我的应用程序。我将首先向您展示的是主模块,它提供了我的应用程序的根(导航、路由器、子导航和内容区域)。
在继续深入之前,我将解释我拥有什么、我想要什么以及为什么。检查此屏幕截图:
您可以看到不同的页面(帐户、频道、播放列表...)。这些页面列在 mainNav 中。每个页面都提供一个子菜单(在本例中名为 sidenav)和一个内容。我知道这是一个很常见的设计:)。
让我们更深入。我有一个名为 MainComponent 的主要角度组件。这是我的根组件。
main.component.ts
@Component({
selector: 'app-view',
directives: [ Devtools, MainNavComponent, SidenavLayoutComponent ],
template: `
<ngrx-devtools *ngIf="prodEnv === false"></ngrx-devtools>
<cmp-main-nav></cmp-main-nav>
<cmp-main-layout [prodEnv]="prodEnv"></cmp-main-layout>
`
})
@RouteConfig([
{ path: '/home', name: 'Home', component: HomeComponent, useAsDefault: true },
{ path: '/medias', name: 'Medias', component: MediasComponent },
])
export class MainComponent {
private prodEnv: boolean = initialState.prodEnv;
constructor (private _router:Router, private _store:Store<AppStore>) {
_router.subscribe(url => _store.dispatch(changeUrl(url)));
}
}
让我们看一下 MainNavComponent 显然...渲染 mainNav 部分。
mainNav.component.ts
@Component({
selector: 'cmp-main-nav',
directives: [ ROUTER_DIRECTIVES, MainLinkComponent ],
styleUrls: ['src/modules/component@main/src/styles/mainNav.css'],
template: `
<nav class="main-nav">
<ul>
<cmp-main-link [routeName]="['Home']" [icon]="'face'">Account</cmp-main-link>
<cmp-main-link [routeName]="['Home']" [icon]="'face'">Channel</cmp-main-link>
<cmp-main-link [routeName]="['Home']" [icon]="'face'">Playlist</cmp-main-link>
<cmp-main-link [routeName]="['Home']" [icon]="'face'">Medias</cmp-main-link>
<cmp-main-link [routeName]="['Home']" [icon]="'face'">Security</cmp-main-link>
</ul>
</nav>
`
})
export class MainNavComponent { }
最后,sidenavLayout.component.ts 将 sidenav 包裹在 angular material component 内,并使用 router-outlet 显示宿主组件提供的内容(参见 main.component.ts:
@Component({
selector: 'cmp-main-layout',
directives: [ /* ... */ ],
styleUrls: [ /* ... */ ],
template: `
<md-sidenav-layout [style.right]="prodEnv ? '' : '30%'" class="sidenav-layout-wrapper">
<md-sidenav class="sidenav" mode="side" [opened]="sidenavIsOpened">
<ul>
<li><cmp-sidenav-link [icon]="'home'" [routeName]="['Home']">Home</cmp-sidenav-link></li>
<li><cmp-sidenav-link [icon]="'input'" [routeName]="['Medias']">Médias</cmp-sidenav-link></li>
</ul>
<button md-button (click)="closeSidenav()">CLOSE</button>
</md-sidenav>
<button md-button (click)="openSidenav()">OPEN</button>
<router-outlet></router-outlet>
</md-sidenav-layout>
`
})
export class SidenavLayoutComponent {
/* ... */
}
你想要什么?
我之前说过我已经构建了一个模块加载器。我希望我的页面(帐户、频道...)成为模块。所以一个“模块”为我提供了:
- sidenav 内容(是的,页面有不同的侧边栏)
- 一个内容(它将被放置在绿色内容区域内)
目前,侧边栏在我的所有应用中都是相同的。我正在寻找一种能够根据页面更新侧边栏的方法。
你有什么尝试?
我已尝试删除 SidenavLayoutComponent。一个页面(例如帐户)为我提供了一个AccountComponent。该组件包含 sidenav 和内容。然后,我可以通过<router-outlet> 将这个AccountComponent 包含在我的main.component.ts 中。
但是不:假设我想在我的 sidenav 中放入一些通用的东西。我需要把这个通用内容放在每个 modules(页面)上。我真的很想拥有一个 'root' sidenav。然后模块将内容放入。 (还有其他原因,但没关系)。
你想要什么?
看看这段代码。它必须在SidenavLayoutComponent 类中:
updateSidenavContent() {
// @todo : retrieve the template of the host component (from the _router) and insert it into the template.
// Maybe using this :
// this._router._outlet._componentRef.__zone_symbol__value.instance
}
constructor (private _router:Router) {
// only if the host component have changed :)
this._router.subscribe(route => this.updateSidenavContent());
}
我想从实例(或类,但这很奇怪)中获取表示组件模板的格式化字符串。
所有这些阅读都是为了问这个问题?!
我真的怀疑像这样检索模板是否是一种解决方案。所以我提出了我的案例,让你能够找到另一个解决方案,也许更好。
我对 Angular 2 比较陌生,所以也许我错过了一些重要的东西。
我不想向你展示我所有的环境,这个“模块加载器”可能很奇怪。我想我们需要知道的都在这里。
谢谢!
【问题讨论】:
-
我知道this answer。但我不知道是否可以动态添加
directives。我不这么认为。 编辑: 如果我使用_router,也许我不需要指令。我正在尝试这个。
标签: javascript angular