iT邦幫忙

2017 iT 邦幫忙鐵人賽
DAY 28
2
Modern Web

Angular 2 之 30 天邁向神乎其技之路系列 第 28

[Day 28] Angular 2 製作 tab 元件

前言

tab 就是可以分頁的標籤

如果有用 Bootstrap,那要用 tab 就會很簡單。

<ul class="nav nav-tabs">
    <li class="active"><a data-toggle="tab" href="#home">Home</a></li>
    <li><a data-toggle="tab" href="#menu1">Menu 1</a></li>
    <li><a data-toggle="tab" href="#menu2">Menu 2</a></li>
    <li><a data-toggle="tab" href="#menu3">Menu 3</a></li>
</ul>

<div class="tab-content">
    <div id="home" class="tab-pane fade in active">
      <h3>HOME</h3>
      <p>......</p>
    </div>
    <div id="menu1" class="tab-pane fade">
      <h3>Menu 1</h3>
      <p>......</p>
    </div>
    <div id="menu2" class="tab-pane fade">
      <h3>Menu 2</h3>
      <p>......</p>
    </div>
    <div id="menu3" class="tab-pane fade">
      <h3>Menu 3</h3>
      <p>......</p>
    </div>
</div>

但我們今天用 Angular 2 來硬幹一個!

Tab

實現一個 tab 大概會長這樣

<tabs>
    <tab>
        <p>This Tab Content 1</p>
    </tab>
    <tab>
        <p>This Tab Content 1</p>
    </tab>
    <tab>
        <p>This Tab Content 1</p>
    </tab>
</tabs>

我們並不想寫成這樣

<tabs [contents]="[...]"></tabs>

把所有 tab 的內容當變數傳遞,這會增加閱讀的難度。我們想要的是顯示層次明確的樣子,這樣的話就會用到 @ContentChild 裝飾器。

tab.ts

import {Component,Input} from '@angular/core';

@Component({
    selector: 'tab',
    template: `
        <p [hidden]="!show">
            <ng-content></ng-content>
        </p>
    `
})
export class TabComponent {
    @Input()
    tabTitle:string;

    show:boolean = false;
}

tabs.ts

import {Component,ContentChildren,QueryList,AfterContentInit} from '@angular/core';
import {TabComponent} from './tab';

@Component({
    selector: 'tabs',
    template: `
       <ul class="tab-list">
           <li *ngFor="let tab of tabs" [class.active]="selectedTab===tab" (click)="onSelect(tab)">
               {{tab.tabTitle}}
           </li>
       </ul>
       <ng-content></ng-content>
    `,
    styles: [`
        .tab-list{
            list-style:none;
            overflow:hidden;
            padding:0;
            color: white;
        }

        .tab-list li{
            cursor:pointer;
            float:left;
            width:60px;
            height:30px;
            line-height:30px;
            text-align:center;
            background-color:gray;
        }

        .tab-list li:hover{
            background-color:#424242;
        }
        .tab-list li.active{
            background-color:black;
        }
    `]
})
export class TabsComponent implements AfterContentInit {
    @ContentChildren(TabComponent)
    tabs:QueryList<TabComponent>;
    
    selectedTab:TabComponent;

    ngAfterContentInit() {
        this.select(this.tabs.first);
    }

    onSelect(tab) {
        this.select(tab);
    }

    select(tab) {
        this.tabs.forEach((item)=>{
            item.show = false;
        });

        this.selectedTab = tab;
        this.selectedTab.show = true;
    }
}

app.ts

import {Component,ContentChildren,QueryList} from '@angular/core';
import {TabsComponent} from './tabs';
import {TabComponent} from './tab';

@Component({
    selector: 'my-app',
    template: `
        <h2>App Component</h2>
        <tabs>
            <tab tabTitle="First">
                <p>This Tab Content 1</p>
            </tab>
            <tab tabTitle="Second">
                <p>This Tab Content 2</p>
            </tab>
            <tab tabTitle="third">
                <p>This Tab Content 3</p>
            </tab>
        </tabs>
    `,
    directives: [TabsComponent,TabComponent]
})
export class AppComponent {
}

範例

Plunker


上一篇
[Day 27] Angular 2 裝飾器 @ViewChild
下一篇
[Day 29] Angular 2 @Directive
系列文
Angular 2 之 30 天邁向神乎其技之路31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言