[Angular]module間でコンポーネントを共有する

## 概要

- Reactではコンポーネントはimportすればどこからでも使うことができるが、Angularでは一手間加えないとできなかったのでやり方のメモ

## やり方

- 共通コンポーネント用のSharedModuleを作成してそれらを各moduleでimportすることで使えるようになる

### サンプル

- 以下のようなhomeモジュールとaboutモジュールでCustomButtonコンポーネントを共有したい場面を想定して説明します

```zsh
% tree src/app/
src/app/
├── app-routing.module.ts
├── app.component.ts
├── app.module.ts
├── custom-button
│   └── custom-button.component.ts
├── about
│   ├── about-routing.module.ts
│   ├── about.component.ts
│   └── about.module.ts
└── home
    ├── home-routing.module.ts
    ├── home.component.ts
    └── home.module.ts
```

### SharedModuleを作成

- 共有コンポーネントを管理する`SharedModule`を作成します

```zsh
ng generate module shared
```

- 生成された`shared.module.ts`に共有したいCustomButtonの定義を追加します
    - declarationsとexportsの2か所に追加する必要があるので注意
- 共有したいコンポーネントを新しく作るときは同じように追加していくことになります

```ts:src/app/shared/shared.module.ts
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { CustomButtonComponent } from '../custom-button/custom-button.component';

@NgModule({
  declarations: [CustomButtonComponent],
  imports: [CommonModule],
  exports: [CustomButtonComponent],
})
export class SharedModule {}
```

### AppModuleでSharedModuleを読み込む

- 作成したSharedModuleを`app.module.ts`で読み込むようにします
    - importsに追加します
- 共有コンポーネント(この例ではCustomButton)の定義が入っている場合は消しておきます

```ts:src/app/app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { SharedModule } from './shared/shared.module';

@NgModule({
  declarations: [AppComponent],
  imports: [BrowserModule, AppRoutingModule, SharedModule],
  providers: [],
  bootstrap: [AppComponent],
})
export class AppModule {}
```

- ここまでが事前準備的なところです

### 共有コンポーネントを使いたいモジュールでSharedModuleを読み込む

- 今回の例でいうとhomeモジュールとaboutモジュールでCustomButtonを使いたいためそれぞれのmoduleでSharedModuleを読み込むようにします
    - それぞれimportsに追加します

```ts:src/app/home/home.module.ts
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';

import { HomeRoutingModule } from './home-routing.module';
import { HomeComponent } from './home.component';
import { SharedModule } from '../shared/shared.module';

@NgModule({
  declarations: [HomeComponent],
  imports: [CommonModule, HomeRoutingModule, SharedModule],
})
export class HomeModule {}
```

```ts:src/app/about/about.module.ts
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';

import { AboutRoutingModule } from './about-routing.module';
import { AboutComponent } from './about.component';
import { SharedModule } from '../shared/shared.module';

@NgModule({
  declarations: [AboutComponent],
  imports: [CommonModule, AboutRoutingModule, SharedModule],
})
export class AboutModule {}
```

- これで完成です！
- homeモジュールとaboutモジュール内で`<app-custom-button></app-custom-button>`が使えるようになりました

### まとめ

- 共有したいコンポーネントはSharedModuleで管理してappモジュールと、コンポーネントを使いたいモジュールでimportすることで使い回せるようになりました
- appモジュールでもimportしないといけないのが個人的にはまりどころでした

## 参考ページ

- https://stackoverflow.com/questions/39486029/share-component-between-2-modules
- https://angular.jp/guide/sharing-ngmodules