2017-10-10 167 views
1

我試圖做一個可重複使用的選項卡組件,並且對如何遍歷組件中的多個ContentChildren(已更正)將它們包裝在html中感到困惑。Angular 2 - 包裝組件兒童

我有一個組件在我看來

<demo-tabs> 
    <a routerLink="/some/link">Tab 1</a> 
    <a routerLink="/some/other/link">Tab 2</a> 
    <a routerLink="/some/third/link">Tab 3</a> 
</demo-tabs> 

我想爲呈現像這樣:

<ul> 
    <li><a routerLink="/some/link">Tab 1</a></li> 
    <li><a routerLink="/some/other/link">Tab 2</a></li> 
    <li><a routerLink="/some/third/link">Tab 3</a></li> 
<ul> 

它似乎並不像我可以在ng-content嵌入含量是我第一次嘗試,並且下面的模板被炸掉了ExpressionChangedAfterItHasBeenCheckedError

@Component({ 
    selector: 'demo-tabs', 
    template: `<ul class="tabs"> 
    <li *ngFor="let a of links"> 
     {{a}} 
    </li> 
    </ul>`}) 
export class TabsComponent implements OnInit { 
    @ContentChildren('a') links: TemplateRef<any>; // corrected. I originally had this as @ViewChildren 

    constructor() { } 

    ngOnInit() { 
    } 

} 

回答

2

首先,這些鏈接不是用於Tabs組件的@ViewChildren() - 它們是@ContentChildren(),因爲@ViewChildren()必須在組件的模板中聲明,而@ContentChildren()來自外部聲明 - 只是像你一樣。

爲了能夠以這種方式分離內容,您需要使用非常簡單的自定義結構指令「標記」所有元素(如下所示),以便您可以將它們作爲TabsComponent中單獨項目的列表。

link.directive.ts

import {Directive, TemplateRef} from '@angular/core'; 

@Directive({ 
    selector: '[appLink]' 
}) 
export class AppLinkDirective { 
    constructor(public template: TemplateRef<any>) { } 
} 

這是一個可以接受的HTML模板作爲DI注入令牌的結構指令。此項目的模板是我們實際需要呈現到TabsComponent的模板中的模板。

那麼,讓我們來紀念我們的項目:

app.component.html

<app-demo-tabs> 
    <a *appLink routerLink="/some/link">Tab 1</a> 
    <a *appLink routerLink="/some/other/link">Tab 2</a> 
    <a *appLink routerLink="/some/third/link">Tab 3</a> 
</app-demo-tabs> 

最後,使它們在組件的模板:

tabs.component.ts

import {Component, ContentChildren, OnInit, QueryList} from '@angular/core'; 
import {AppLinkDirective} from './link.directive'; 

@Component({ 
    selector: 'app-demo-tabs', 
    template: ` 
     <ul class="tabs"> 
      <li *ngFor="let link of links"> 
       <ng-template [ngTemplateOutlet]="link?.template"></ng-template> 
      </li> 
     </ul>` 
}) 
export class TabsComponent implements OnInit { 

    @ContentChildren(AppLinkDirective) 
    links: QueryList<AppLinkDirective>; 

    constructor() { 
    } 

    ngOnInit() { 
    } 

} 

當然,您需要在某個模塊中導入此僞指令,以便它可以在模板中使用。

+0

一些替代解決方案https://stackblitz.com/edit/angular-wqjlbw?file=app%2Fapp.module.ts但我喜歡你的回答 – yurzui

+0

@yurzui,是的,這當然是可能的,而且不是一個糟糕的選擇儘管如此,我還是喜歡儘可能少地放入html中 - 這樣它就可以更清晰地閱讀,重要的東西也不會在一堆次要的HTML內容中隱藏起來。 –

+0

完美運作。我也看了@ yurzui的解決方案,我也看到了它的工作方式,但我同意,這個更清晰(無論如何,對我來說都是一個小菜鳥)。謝謝! – BLSully