2016-08-23 47 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 
     } 
    ] 
    } 
]);