2016-12-08 36 views
8

Đây là câu hỏi về cách thực hiện chức năng được yêu cầu theo cách "đúng" với Angular 2.Angular2: Hiển thị các thành phần "thanh công cụ" khác nhau tùy theo điều hướng chính

Ứng dụng của tôi có menu điều hướng, thanh công cụ, và một khu vực nội dung. Dữ liệu sau chứa chính <router-outlet> và hiển thị các chế độ xem khác nhau như danh sách và chi tiết.

Điều tôi muốn đạt được là thanh công cụ hiển thị các thành phần khác nhau, tùy thuộc vào thành phần/chế độ xem được hiển thị trong khu vực nội dung. Ví dụ, thành phần danh sách cần một điều khiển tìm kiếm trong thanh công cụ, trong khi thành phần chi tiết cần một nút lưu.

A) nỗ lực đầu tiên của tôi là thêm một (tên) <router-outlet> vào thanh công cụ và hiển thị các thành phần thanh công cụ dựa trên các tuyến đường tĩnh. Điều gì cảm thấy sai về điều này:

  1. Mối quan hệ thanh công cụ nội dung tĩnh được kết hợp quá lỏng lẻo cho khẩu vị của tôi.
  2. Quan hệ hiển thị (và có thể thay đổi) trong URL.
  3. Thanh công cụ giữ đường dẫn này ngay cả khi người dùng điều hướng đi.

B) nỗ lực thứ hai của tôi là để di chuyển phải nhất thiết để các thành phần thanh công cụ (còn sử dụng ổ cắm thanh công cụ có tên), trong đó các cặp vợ chồng quan điểm thành phần chính của ngOnInit, nó chặt chẽ hơn. Có gì mùi hôi:

  1. A2
  2. A3, để ngăn chặn điều này tôi có thể "rõ ràng" ổ cắm thanh công cụ trên ngOnDestroy, nhưng tôi đã không phát hiện ra như thế nào.

C) Giving router một cơ hội cuối cùng, kể từ khi tôi phát hiện ra rằng loại của công trình này:

const ROUTES: Routes = [ 
    {path: "buildings", children: [ 
     {path: "", component: BuildingListComponent, pathMatch: "full", outlet: "primary"}, 
     {path: "", component: BuildingListToolbarComponent, pathMatch: "full", outlet: "toolbar"}, 
     {path: ":id", component: BuildingDashboardComponent, outlet: "primary"} 
    ]} 
]; 

Ý tưởng là router sẽ chọn con đường phù hợp mỗi ổ cắm . Tuy nhiên, thật không may, nó không hoạt động:

const ROUTES: Routes = [ 
    {path: "buildings", children: [ 
     {path: "list", component: BuildingListComponent, pathMatch: "full", outlet: "primary"}, 
     {path: "list", component: BuildingListToolbarComponent, pathMatch: "full", outlet: "toolbar"}, 
     {path: ":id", component: BuildingDashboardComponent, outlet: "primary"} 
    ]} 
]; 

Dường như (và có thể tình cờ) chỉ hoạt động với đường dẫn trống. Tại sao Oh lý do tại sao?

D) Một chiến lược hoàn toàn khác là làm lại cấu trúc phân cấp thành phần của mình, để mọi thành phần xem chính chứa thanh công cụ thích hợp và sử dụng multi-slot content projection. Đã không cố gắng này, nhưng tôi sợ chạy vào các vấn đề với nhiều trường hợp của thanh công cụ.

Đôi khi, điều này có vẻ là trường hợp sử dụng phổ biến và tôi tự hỏi các chuyên gia của Angular 2 sẽ giải quyết vấn đề này như thế nào. Bất kỳ ý tưởng?

+3

Bạn chỉ có thể thêm các thành phần tự động như thể hiện trong http://stackoverflow.com/questions/36325212/angular-2-dynamic-tabs-with-user -click-selected-components/36325468 # 36325468 Tiêm bộ định tuyến để nhận thông báo về thay đổi tuyến đường và sau đó thêm thành phần phù hợp. Bạn cũng có thể thêm 'dữ liệu' vào các tuyến để định cấu hình ở cấp tuyến mà thành phần nào cần được thêm như được minh họa trong http://stackoverflow.com/questions/38644314/changing-the-page-title-using-the-angular-2- new-router/38652281 # 38652281 –

+0

Cảm ơn bạn Günter, tôi sẽ thử điều này. Tôi cũng đã thử một biến thể khác của cấu hình router, trông có vẻ hứa hẹn (C), nhưng không may mắn. – Zeemee

+0

Tôi đã đăng câu trả lời dựa trên đề xuất của bạn. Một lần nữa, cảm ơn bạn đã đưa tôi đi đúng hướng. – Zeemee

Trả lời

8

Theo gợi ý của Günter Zöchbauer (cảm ơn bạn!), Tôi đã kết thúc việc thêm và xóa các thành phần động vào thanh công cụ. Thành phần thanh công cụ mong muốn được xác định trong thuộc tính dữ liệu của tuyến đường và được đánh giá bởi thành phần trung tâm (thanh điều hướng) có chứa thanh công cụ.
Lưu ý rằng thành phần thanh điều hướng không cần biết bất kỳ điều gì về các thành phần thanh công cụ (được xác định trong các mô-đun làm đẹp).
Hy vọng điều này sẽ giúp ai đó.

tòa nhà routing.module.ts

const ROUTES: Routes = [ 
    {path: "buildings", children: [ 
     { 
      path: "", 
      component: BuildingListComponent, 
      pathMatch: "full", 
      data: {toolbar: BuildingListToolbarComponent} 
     }, 
     { 
      path: ":id", 
      component: BuildingDashboardComponent, 
      data: {toolbar: BuildingDashboardToolbarComponent} 
     } 
    ]} 
]; 

@NgModule({ 
    imports: [ 
     RouterModule.forChild(ROUTES) 
    ], 
    exports: [ 
     RouterModule 
    ] 
}) 
export class BuildingsRoutingModule { 
} 

navbar.component.html

<div class="navbar navbar-default navbar-static-top"> 
    <div class="container-fluid"> 
     <form class="navbar-form navbar-right"> 
      <div #toolbarTarget></div> 
     </form> 
    </div> 
</div> 

navbar.component.ts

@Component({ 
    selector: 'navbar', 
    templateUrl: './navbar.component.html', 
    styleUrls: ['./navbar.component.scss'] 
}) 
export class NavbarComponent implements OnInit, OnDestroy { 

    @ViewChild("toolbarTarget", {read: ViewContainerRef}) 
    toolbarTarget: ViewContainerRef; 

    toolbarComponents: ComponentRef<Component>[] = new Array<ComponentRef<Component>>(); 
    routerEventSubscription: ISubscription; 


    constructor(private router: Router, 
       private componentFactoryResolver: ComponentFactoryResolver) { 
    } 

    ngOnInit(): void { 
     this.routerEventSubscription = this.router.events.subscribe(
      (event: Event) => { 
       if (event instanceof NavigationEnd) { 
        this.updateToolbarContent(this.router.routerState.snapshot.root); 
       } 
      } 
     ); 
    } 

    ngOnDestroy(): void { 
     this.routerEventSubscription.unsubscribe(); 
    } 

    private updateToolbarContent(snapshot: ActivatedRouteSnapshot): void { 
     this.clearToolbar(); 
     let toolbar: any = (snapshot.data as {toolbar: Type<Component>}).toolbar; 
     if (toolbar instanceof Type) { 
      let factory: ComponentFactory<Component> = this.componentFactoryResolver.resolveComponentFactory(toolbar); 
      let componentRef: ComponentRef<Component> = this.toolbarTarget.createComponent(factory); 
      this.toolbarComponents.push(componentRef); 
     } 
     for (let childSnapshot of snapshot.children) { 
      this.updateToolbarContent(childSnapshot); 
     } 
    } 

    private clearToolbar() { 
     this.toolbarTarget.clear(); 
     for (let toolbarComponent of this.toolbarComponents) { 
      toolbarComponent.destroy(); 
     } 
    } 
} 

Tài liệu tham khảo:
https://vsavkin.com/angular-router-understanding-router-state-7b5b95a12eab
https://engineering-game-dev.com/2016/08/19/angular-2-dynamically-injecting-components
Angular 2 dynamic tabs with user-click chosen components
Changing the page title using the Angular 2 new router

+0

Bạn có thể muốn xóa mảng toolbarComponents ở cuối phương thức clearToolbar – kboom

Các vấn đề liên quan