ナガモト の blog

Full Cycle Developerを目指すエンジニアが有用そうな技術記事や、ポエムのようなよしなしごとを投稿するブログです。

Angularでタブを実装

先日リリースしたngmt83に改善を加えました。まずはどう変わったのかをご確認ください。

f:id:ngmt83:20190119204949p:plainf:id:ngmt83:20190119204954p:plain
before -> after

skillがすべて一覧表示になって少々見にくかったので、タブで切り替えられるようにしました。まずまず見やすくなったと思います。

どう実現したか

「Angular タブ」でググるとAngular Materialなど便利なコンポーネントを使用したものばかりがヒットします。私のポートフォリオではNES.cssを使用しており、タブは自分で実装する必要がありました。*1

少し探すと、NgComponentOutletという動的にコンポーネントを変更するAngular APIを見つけたので、それを利用することにしました。

公式doc: Angular

わかりやすい解説URL: Dynamic component rendering in Angular 5 with NgComponentOutlet

手順は以下の通りでした。

  1. コンポーネントを切り分ける
  2. NgComponentOutletで特定コンポーネントを表示する状態を作る
  3. ボタンの選択状況で表示するコンポーネントを変更する

コンポーネントを切り分ける

リファクタリングし、Lang, Data House, etcのそれぞれにあたる部分をコンポーネント化しました。特に説明することはなかったです。

NgComponentOutletで特定コンポーネントを表示する状態を作る

まずはapp.module.tsにNgComponentOutletで読み込むコンポーネントを宣言します。私はこれを忘れて少しハマりました。

app.module.ts

  entryComponents: [
    LangComponent
  ],

そしてskill.component.tsで該当コンポーネントをテンプレートに展開できるようにします。

skill.component.ts

import { Component } from '@angular/core';
import { LangComponent } from './lang/lang.component';

@Component({
  selector: 'app-skill-component',
  templateUrl: './skill.component.html',
  styleUrls: ['./skill.component.scss']
})
export class SkillComponent {
  lang = LangComponent;
}

最後にngComponentOutletに表示したいコンポーネントを指定します。

skill.component.html

    <ng-container *ngComponentOutlet="lang"></ng-container>

これでngComponentOutletを使用してコンポーネントを表示できることが確認できました。

ボタンの選択状況で表示するコンポーネントを変更する

まずapp.module.tsに表示したいコンポーネントすべてを宣言します

app.module.ts

  entryComponents: [
    LangComponent,
    DataStoreComponent,
    ToolsComponent
  ],

そしてskill.component.tsで複数のコンポーネント配列に格納し、選択されているコンポーネントを切り替える関数を作成します。

skill.component.ts

import { Component } from '@angular/core';
import { LangComponent } from './lang/lang.component';
import { DataStoreComponent } from './data-store/data-store.component';
import { ToolsComponent } from './tools/tools.component';

@Component({
  selector: 'app-skill-component',
  templateUrl: './skill.component.html',
  styleUrls: ['./skill.component.scss']
})
export class SkillComponent {
  private tabs = [
    {
      label: 'Languege, Framework',
      component: LangComponent
    },
    {
      label: 'Data Store',
      component: DataStoreComponent
    },
    {
      label: 'etc',
      component: ToolsComponent
    }
  ];

  private selectedTabNum = 0;

  selectedTab = this.tabs[this.selectedTabNum];

  onClickButton(i): void {
    this.selectedTab = this.tabs[i];
  }
}

切り替え操作を行うボタンをhtmlに実装し、クリック時に切り替え操作を行う関数を呼び出します。

skill.component.html

  <div fxLayout="row" fxLayoutAlign="space-around">
    <button fxFlex="30" type="button" class="nes-btn" (click)="onClickButton(0)">Lang</button>
    <button fxFlex="30" type="button" class="nes-btn" (click)="onClickButton(1)">Data Store</button>
    <button fxFlex="30" type="button" class="nes-btn" (click)="onClickButton(2)">etc</button>
  </div>
  <h2>{{selectedTab.label}}</h2>
  <div fxLayout="column">
    <div fxLayout="row" fxLayoutAlign="space-between center">
      <div fxFlex="40" fxFlex.lt-sm="50" fxFlex.gt-sm="30"></div>
      <div fxFlex="60" fxFlex.lt-sm="50" fxFlex.gt-sm="70"fxLayout="row" fxLayoutAlign="space-between center">
        <div class="t-left measure">low</div>
        <div class="t-right measure">high</div>
      </div>
    </div>

    <ng-container *ngComponentOutlet="lang"></ng-container>

  </div>

これで、ボタンの選択状況に応じてコンポーネントが切り替わるようになりました。興味があればぜひ試してみてください。

ngmts-portfolio.netlify.com

最後に

Angularでタブの実装をやってみましたが、デザインにこだわりがなければAngular Materialを使用すると簡単にアニメーションまでついたタブを実装できます。とりあえずアプリが作りたいんだ!という人にはAngularとAngular Materialの組み合わせがおすすめです。