2016-08-23 48 views
1

我正在使用Angular 2(RC5)和Typescript写SPA。我有一个主导航栏(使用Bootstrap 4 Alpha 3)和一个定制设计的侧栏。这里有一个图:在Angular2中,如何根据活动路线更改侧边栏?

enter image description here

的这里的目的是导航到一个主要的“应用程序”使用的顶部导航栏中。目前我有3个主要的应用程序 - 追踪器,Proboard和设备。一旦主应用程序被激活,边栏上的链接就会改变。在上图中,侧栏显示了“Proboard”应用程序的链接。

如何我可以改变基于活动路由侧边栏上的内容,而无需一堆的“* ngIf”在我的HTML声明?

我想在我的代码中的JSON对象的地方(可能是从后端API检索),将列出每个应用程序的链接。类似:

[ 
    { proboard: [ 
    { label: 'Home', link: '/proboard', icon: 'fa-home'}, 
    { label: 'Candidates', link: '/proboard/candidates', icon: 'fa-users'}, 
    { label: 'New', link: '/proboard/candidate/new', icon: 'fa-new-user; } ] 
    }, 
    { tracker: [...] }, 
    { equipment: [...] } 
] 

然后,当用户将导航到在顶部导航栏的链接之一,边栏将与上述阵列中的内容来填充,使用在HTML的NgFor

任何建议或链接,将不胜感激。

回答

1

我做了同样的事情,这里是我如何解决它。

  1. 创建的菜单中最上面的应用程序组件
  2. 创建一个服务,并在服务
  3. 创建一个可订阅的主题流改变路线保持一个共同的路由表
  4. 订阅该流来自菜单所在的组件
  5. 从当前组件中发出subcription.next,该组件使用菜单在组件中设置所选路径。

您可以通过其他类型的组件交互实现此目的。下面是从角2个文档上的详细信息:https://angular.io/docs/ts/latest/cookbook/component-communication.html

+0

当你说'subscribable subject stream'时你说的是可观察的,对吧?我完全可以看到这将如何工作,但感觉有点矫枉过正。 –

+0

是的,我正在谈论一个可观察的主题流。当然有多种方法可以做到这一点。这是我能想到的最干净的方式,对于你正在尝试做的事情可能是过度的。 –

+0

这或多或少是我实际完成这个的。 –

1

这里有一个可能的解决方案。

由于每个三个应用程序的,就是要完全独立(如你定义它),你可以做一个完全独立的“SideBarComponent”,你可以在每个应用程序重复使用。

既然你可以给一个组件要与@input(变量)的任何信息,您可以提供它的标签,链接,它需要的图标的列表。例如:

EquipmentComponent.ts

sideBarLinks: any = { proboard: [ 
    { label: 'Home', link: '/proboard', icon: 'fa-home'}, 
    { label: 'Candidates', link: '/proboard/candidates', icon: 'fa-users'}, 
    { label: 'New', link: '/proboard/candidate/new', icon: 'fa-new-user; } ] 
} 

EquipmentComponent.html

<side-bar [buttons]='sideBarLinks'></side-bar> 

SideBarComponent.ts

@Input() 
buttons: any; 

SideBarComponent.html

// Use 'buttons' to construct your buttons in the sidebar. Possibly using an ng repeater in this template. 

即使你最终不会实现这个正好,我希望这可以让你使用中的可重用组件的方向角2

想希望这是有帮助的!

这里比你需要了解组件交互的所有内容都多:https://angular.io/docs/ts/latest/cookbook/component-communication.html

+0

这是一个伟大的建议,它符合我的思考方式这样的事情。虽然我并不陌生编程,但我对网络编程和Angular2都很陌生,所以这肯定让我想到了可重用性。 –

+1

啊,我觉得。我从游戏切换到网络编程,并有同样的冒险:P 以下是关于如何使您的Angular代码可重用的一些非常好的资源(它们是为Angular 1.xx编写的,但是由Angular团队按顺序推荐过渡到2,所以相同的设计思路) https://www.airpair.com/angularjs/posts/component-based-angularjs-directives https://www.youtube.com/watch?v=UMkd0nYmLzY http://teropa.info/blog/2014/10/24/how-ive-improved-my-angular-apps-by-banning-ng-controller.html 最后一个链接中的视频特别真棒。 – Adam

1

2可能的方式

1 - 在侧边栏组件,订阅路由器的变化,但你最终会使用*ngIf

@Input() 
data: any; 

constructor(private router: Router) { 
    router.changes.subscribe((val) => { 
     if(val === 'noSidebarRoute'){ 
      this.navButtons= false; 
     } 
     else { 
      this.navButtons= navData; 
     } 
    }) 
} 

然后在父组件模板

@Component({ 
    selector: 'parent', 
    template: `<side-bar [data]='navData'></side-bar>` 
}); 

export class Parent{ 

navData = [ 
    { proboard: [ 
     { label: 'Home', link: '/proboard', icon: 'fa-home'}, 
     { label: 'Candidates', link: '/proboard/candidates', icon: 'fa-users'}, 
     { label: 'New', link: '/proboard/candidate/new', icon: 'fa-new-user; } 
    ]}, 
    { tracker: [...] }, 
    { equipment: [...] } 
]} 

2 - 在您的应用程序康波nent(或侧边栏父组件),请使用resolver.resolveComponent动态地将侧边栏组件添加到您的应用中,这样您就不会使用数据绑定(*ngIf)。

sidebarCmpRef:ComponentRef<any>; 

constructor(private router: Router, 
      private viewContainerRef:ViewContainerRef, 
      private resolver:ComponentResolver) { 

    router.changes.subscribe((val) => { 
     if(val === 'noSidebarRoute'){ 
      if(this.sidebarCmpRef){ 
       this.sidebarCmpRef.destroy(); 
       this.sidebarCmpRef 
      } 
     } 
     else{ 
      this.AddSidebar(); 
     } 
    }) 
} 

AddSidebar(){ 
    if(!this.cmpRef){ 
     this.resolver.resolveComponent(<Type>SideBar) 
      .then((factory:ComponentFactory<any>) => { 
      this.cmpRef = this.viewContainerRef.createComponent(factory); 
      this.cmpRef.instance.buttons= navData; 
     }); 
    } 
} 
+0

有趣。在#1中,'val'将成为主动路线吗?如果不是'this.show = false'或'this,我会反复。show = true'我可以做一些类似'this.linkDescriptions = desc'的地方,其中'desc'是我在OP中提到的JSON数组中的一个元素? –

+0

确实有''路由器'上的变更'属性?我没有在参考文献中看到它。 – estus

+1

@JohnDibling是的,你可以 –

1

我宁愿采用有角度的基本方法,即加载路线内的儿童。

定义你的main.route如下

import { NgModule } from '@angular/core'; 
import { Routes, RouterModule } from '@angular/router'; 
import { PageNotFoundComponent } from './shared/components/pagenotfound.component'; 

export const appRoutes: Routes = [ 
    { 
    path: 'tracker', 
    loadChildren: 'app/tracker/module#trackermodule', 
    }, 
    { 
    path: 'proboard', 
    loadChildren: 'app/proboard/module#proboard', 
    }, 
{ 
    path: 'equiment', 
    loadChildren: 'app/equiment/module#equiment', 
    }, 
    { 
    path: '**', 
    component: PageNotFoundComponent 
    } 
]; 

@NgModule({ 
    imports: [RouterModule.forRoot(appRoutes)], 
    declarations: [ 
     PageNotFoundComponent 
    ], 
    exports: [RouterModule] 
}) 

export class AppRouterModule { 
} 

那么你的孩子/子模块中的路由配置应该是

import { RouterModule } from '@angular/router'; 
import { CssComponent } from './view'; 
import { RadioAndCheckBoxComponent } from './radio-and-checkbox/view'; 

export const RouteComponents = [ 
    CssComponent 
]; 

export const Routes = RouterModule.forChild([ 
    { 
    path: '', 
    component: equimentComponent, 
    children: [ 
     { 
     path: 'Home', 
     component: HomeComoponent 
     }, 
     { 
     path: 'Candidates', 
     component: CandidatesComoponent 
     } 
    ] 
    } 
]);