2017-04-27 25 views
3

私のAngular(v4)アプリでは、パンくずリストモジュールを作成しようとしています。私はそうAngular4:ルータの `data`プロパティを使ってパンくずリストコンポーネントを渡します。

{ path: '', component: HomeComponent, data: {breadcrumb: 'home'}} 

のようなルータのdataプロパティでブレッドクラムの情報を格納しかし、私がやりたいことは、データプロパティにコンポーネント店あり、その後、ブレッドクラムモジュールエキスを持っ示唆、this S.O. questionが役に立ったと評価していレンダリングします。私は角Dynamic Component Loader guidehelpful blog post後、この

{ path: '', component: HomeComponent, data: {breadcrumb: CustomViewComponent}} 

のようなパンくずモジュールと対話することができ、私はコンポーネントをレンダリング私のブレッドクラムを作成しようとしてきました。この操作を行います。

import { Component, Input, OnInit, AfterViewInit, 
    ViewChild, ViewContainerRef, ComponentFactoryResolver } from '@angular/core'; 
import { Router, ActivatedRoute, NavigationEnd } from '@angular/router'; 
import 'rxjs/add/operator/filter'; 

import { MainLogoComponent } from '../my-material/main-logo/main-logo.component'; 

@Component({ 
    selector: 'app-breadcrumbs', 
    template: `<div #parent></div>`, 
    styleUrls: ['./breadcrumbs.component.scss'] 
})  
export class BreadcrumbsComponent implements OnInit, AfterViewInit { 
    breadcrumbs: Array<any>; 
    @ViewChild('parent', {read: ViewContainerRef}) parent: ViewContainerRef; 

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

    ngOnInit() { 
    this.router.events 
     .filter(event => event instanceof NavigationEnd) 
     .subscribe(event => { // note, we don't use event 
     this.breadcrumbs = []; 
     let currentRoute = this.route.root, 
      url = ''; 
     do { 
      let childrenRoutes = currentRoute.children; 
      currentRoute = null; 
      childrenRoutes.forEach(route => { 
      if(route.outlet === 'primary') { 
       let routeSnapshot = route.snapshot; 
       url += '/' + routeSnapshot.url.map(segment => segment.path).join('/'); 
       this.breadcrumbs.push({ 
       label: route.snapshot.data.breadcrumb, 
       url: url }); 
       currentRoute = route; 
      } 
      }) 
     } while(currentRoute); 
     }) 
    } 

    ngAfterViewInit() { 
    const logoComponent = this.componentFactoryResolver 
     .resolveComponentFactory(this.breadcrumbs[0]); // at the moment just using breadcrumbs[0] for simplicity 
    this.parent.createComponent(logoComponent); 
    } 
} 

残念ながら、それはと思われますルートデータプロパティはコンポーネントを格納できません。デバッグコンソールを使用してデータプロパティが保存される{data: {breadcrumb: }}

このコードを動作させる方法を知っている人、または他のビューを使用するブレッドクラムコンポーネントを構築する目的を達成するためのよりよい方法を提案した場合コンポーネント、私は大幅にそれを感謝します!

PS:私はdataプロパティを省略した場合、ちょうど手動でそのようなページにMainLogoComponentを追加するブレッドクラム・コンポーネントを尋ねる:

ngAfterViewInit() { 
    const logoComponent = this.componentFactoryResolver.resolveComponentFactory(MainLogoComponent); 
    this.parent.createComponent(logoComponent); 
    } 

それは

そして、完全を期すため、コードの作品関連するルートのために。ここで

const routes: Routes = [ 
    { 
    path: 'calendar', 
    data: { 
     breadcrumb: MainLogoComponent 
    }, 
    canActivate: [ AuthGuard ], 
    children: [ 
     { 
     path: '', 
     component: CalendarComponent 
     } 
    ] 
    } 
]; 

UPDATE

関連NgModuleです:

@NgModule({ 
    imports: [ 
    CommonModule, 
    MyMaterialModule 
    ], 
    exports: [ 
    BreadcrumbsComponent 
    ], 
    entryComponents: [BreadcrumbsComponent, MainLogoComponent], 
    declarations: [BreadcrumbsComponent] // MainLogoComponent is declared in MyMaterialModule 
}) 
export class BreadcrumbsModule { } 
+1

は(...私が今実現しています、本当に独自のファイルを必要としません)あなたがしようとしたことがあり、ここでパンくずリストビューコンポーネント

import { Component, HostBinding } from '@angular/core'; import { DomSanitizer } from '@angular/platform-browser'; @Component({ selector: 'app-calendar-breadcrumb', templateUrl: './calendar-breadcrumb.component.html', styleUrls: ['./calendar-breadcrumb.component.scss'] }) export class CalendarBreadcrumbComponent { // Modify this components parent element so that it is displayed with flexbox @HostBinding('attr.style') style = this.sanitizer .bypassSecurityTrustStyle('display: flex; flex-direction: row;'); constructor(private sanitizer: DomSanitizer) {} } 

の例だと、関連するビューファイルには、 'ngAfterViewInit'から' subscribe'ハンドラにコードを移動するには? – yurzui

+0

したがって、コンポーネントの動的ロードは 'ngAfterViewInit()'コールバック中に行う必要があります( 'ngOnInit()'の間は実行できません)。私は 'init'作業のすべてを' ngAfterViewInit'に移動し、 'subscribe'ハンドラの中にコンポーネントを作成しようとしました。エラーが発生します。私は "MainLogoComponentのコンポーネントが見つかりません"というエラー( 'data'プロパティが空でないことを示していますが、' data'の中の 'MainLogoComponent'を調べてみましょう:〜' function MainLogoComponent – John

+0

'MainLogoComponentのためのコンポーネントファクトリが見つかりません 'というのは、このコンポーネントを' entryComponents'配列に追加する必要があることを意味します。 – yurzui

答えて