タブ切り替え実装 ~JavaScript7割Angular3割~

前提：本来のしたい実装とは、違う形で実装しました。
とりあえず、タブ切り替え実装したい人向けの実装方法です。

<h1>登場ファイル</h1>
home.component.ts

home.component.html

tab.component.ts
tab.component.html

<h1>tab側実装</h1>

```tab.component.ts

import { Component, OnInit } from '@angular/core';
import { Output, EventEmitter } from '@angular/core';

interface tabFormat {
  title:string,
  type:string,
  id:any
}

@Component({
  selector: 'app-tab',
  templateUrl: './tab.component.html',
  styleUrls: ['./tab.component.scss']
})

export class TabComponent implements OnInit {

  /**今は未使用 */
  currentId:string | undefined;
  /**タブ１ */
  domId_1:any;
  /**タブ2 */
  domId_2:any;
  /**タブ3 */
  domId_3:any;
  /**homeクリックイベント渡し */
  @Output() clickEvent = new EventEmitter<any>();

    /**タブリスト*/
  public tabArray:tabFormat[] = [
    {
      title:"tab１",
      type :"tabA",
      id:"tab1"
    },
    {
      title:"tab2",
      type :"tabB",
      id:"tab2"
    },
    {
      title:"tab3",
      type :"tabC",
      id:"tab3"
    }
  ]

  constructor(
  ) { }

  ngOnInit(): void {
    /**初期値選択 tab1 */
    this.domId_1 = document.getElementById('tab1');
    this.domId_1.classList.add('is-active');
  }

    /**タブクリック */
    onClickTab(tabItem:any){
      /**DOM取得 */
      this.domId_1 = document.getElementById('tab1');
      this.domId_2 = document.getElementById('tab2');
      this.domId_3 = document.getElementById('tab3');
      
      /**全てのis-activeリセット */
      this.domId_1.classList.remove('is-active');
      this.domId_2.classList.remove('is-active');
      this.domId_3.classList.remove('is-active');

      /**clickに紐づくclass active付与 */
      if(tabItem == "tab1"){
        this.domId_1.classList.add('is-active');
      }else if(tabItem == "tab2"){
        this.domId_2.classList.add('is-active');
      }else if(tabItem == "tab3"){
        this.domId_3.classList.add('is-active');
      }else {
        return;
      }
      /**子から親コンポーネントにデータ渡し*/
      this.clickEvent.emit(
        this.currentId = tabItem
      );
    }
}


```

```tab.component.html

<div class="container">
    <div class="tab">
      <ul class="tab__list">
        <li class="tab__item">
          <button class="tab_text" type="button" id="tab1"
          (click)="onClickTab(tabArray[0].id)">{{tabArray[0].title}}</button>
        </li>
        <li class="tab__item">
          <button class="tab_text" type="button" id="tab2"
          (click)="onClickTab(tabArray[1].id)">{{tabArray[1].title}}</button>
        </li>
        <li class="tab__item">
          <button class="tab_text" type="button" id="tab3"
          (click)="onClickTab(tabArray[2].id)">{{tabArray[2].title}}</button>
        </li>
      </ul>
    </div>
  </div> 
```

<h1>home側実装</h1>

```home.component.ts
<!-- タブ -->
<app-tab
(clickEvent)="onReceiveEventFromChild($event)"></app-tab>

<p>{{result}}</p>

```

```home.component.html
  /**tab.ts　clickデータ */
  public childData:any;
  /**tab依存画面表示 初期値="tab1" */
  public result:any = "tab1";

  constructor(
    private Location: Location,
  ) { 
  }

  ngOnInit(): void {
  }

  /**tab.tsからclick要素取得 */
  onReceiveEventFromChild(event:any){
    this.childData = event;

    this.dispayActive();
  }
  /**tabに紐づいて画面を切り替えする実装はこちら */
  dispayActive(){
    this.result = this.childData;
  }
  /**戻るボタン */
  backBtnClick(){
    this.Location.back();
  }
```

<h1>説明</h1>

①タブ実装を別コンポーネントに切り分けて実装している。
　→home側で < app-tab > < /app-tab>で呼び出し。
②画面表示する情報は、なるべくts側で用意。
　→tab.tsのtabArrayのように。
③/home画面遷移時の初期選択タブを「tab1」に実装する。
　→tab.ts側　＝　ngOnInitでtab1にis-active付与。
　→home.ts側　＝　public result:any = "tab1";を定義
④emit(子→親へイベントデータ渡し)を用いて、home側でタブに紐付き画面切り替え
　→emitはhtmlで下記のように定義しないと子側から情報取れないみたいです。
　「<app-tab
(clickEvent)="onReceiveEventFromChild($event)"><　/app-tab>」
　補足：ts同士で情報のやり取りをした内容をhtmlに表示するのが普通と思っていましたが、ここの記載を消しちゃうと、エラーになりました。
emit以外の方法で言えば、service側の変数にclickされた情報を格納して、home.tsで呼び出せば、ts間のデータやり取りでhtmlに情報出力できると思いますが、emitの方が簡単で容易でした。

<h1>最後に</h1>
本来は、このような実装方法にしたくなかったのですが、
やり方が分からず暫定的にこのような実装方法をとりあえずしました。

本当は、それぞれtab1,tab2,tab3を書かずに、ngFor等でループしたかったのですが
また次回実装できれば投稿します。