ゼロから始めるstimulus入門2(現実的なものを作る)

## はじめに
前回から引き続いて、ドキュメントを読み進めます。
前回の記事はこちら→[ゼロから始めるstimulus入門1](https://qiita.com/shinry/items/de697c4a679e14a41ffa)
今回は、より具体的な実装をドキュメントを見ながらやっていきます。

## コピーボタンを実装
PIN(個人識別番号)を生成して、ほかのユーザーにアクセス権を付与できるアプリを考えます。
以下のコードは生成されたPINをクリップボードにコピーできる機能です。
```html
<div>
  PIN: <input type="text" value="1234" readonly>
  <button>Copy to Clipboard</button>
</div>
```

## 実装方法1(クリップボードがひとつだけの場合)
### clipboard_controller.js
htmlと見比べながら、読んでいってください。
- `static targets = [ "source" ]`でターゲットを定義。htmlの`data-clipboard-target="source"`と対応
    - `this.sourceTarget`のようにアクセスできるようになる
- `navigator.clipboard`でClipboard APIが呼び出され、writeTextでクリップボードにテキストを書き込む
```js
// src/controllers/clipboard_controller.js
import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
  static targets = [ "source" ]

  copy(event) {
    navigator.clipboard.writeText(this.sourceTarget.value)
  }
}
```


### html
- `data-controller="clipboard"`でclipboard_controller.jsと接続
- `data-clipboard-target="source"`でテキストフィールドを参照
- `data-action="clipboard#copy"`でclipboard_controller.jsのcopyメソッドが呼び出される
```html
<div data-controller="clipboard">
  PIN: <input data-clipboard-target="source" type="text" value="1234" readonly>
  <button data-action="clipboard#copy">Copy to Clipboard</button>
</div>
```

### 実際の画面
PINが一つ表示され、値がコピーできます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1328154/70666d6b-7633-ddb0-8089-c3b195af41a2.png)


## 実装方法2（クリップボードが複数ある場合）
### clipboard_controller.js
jsに変更はありません。
```js
// src/controllers/clipboard_controller.js
import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
  static targets = [ "source" ]

  copy(event) {
    navigator.clipboard.writeText(this.sourceTarget.value)
  }
}
```

### html
jsはいじらずに、inputのvalueだけ変更したPINを追加するとそれぞれコピーすることができます。
```html
<div data-controller="clipboard">
  PIN: <input data-clipboard-target="source" type="text" value="1234" readonly>
  <button data-action="clipboard#copy">Copy to Clipboard</button>
</div>

<div data-controller="clipboard">
  PIN: <input data-clipboard-target="source" type="text" value="3737" readonly>
  <button data-action="clipboard#copy">Copy to Clipboard</button>
</div>
```

### 実際の画面
PINが二つ表示され、それぞれコピーボタンをおしたら、値をコピーできました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1328154/9c054aae-de30-a474-8fc5-b1a88df1201a.png)


## ターゲットの定義について
`static targets`というようなものをつけてtargetを指定していますが、これの意味について深掘っていこうと思います。
```js
export default class extends Controller {
  static targets = [ "source" ]

  // ...
}
```
static配列であるtargetsの中にターゲット名の文字列を探しています。
配列内の各ターゲット名に対して、Stimulusは以下の3つの新しいプロパティをコントローラーに追加しています。
- this.sourceTarget
コントローラーのスコープ内で最初のsourceターゲットを指定する。
sourceターゲットが存在しない場合、このプロパティにアクセスするとエラーが投げられる。
- this.sourceTargets
コントローラーのスコープ内のすべてのsourceターゲットを含む配列を指定する。
- this.hasSourceTarget
sourceターゲットが存在する場合はtrue、存在しない場合はfalseを返す。

## イベントの省略
本来ならば、クリックイベントではclick->をつけますが、アクションの記述でclick->を省略していました。これは、Stimulusが<button>要素に対するアクションのデフォルトイベントとしてclickを定義していいるためです。
他にもいくつかの要素にデフォルトイベントが設定されています。
| 要素               | デフォルトイベント |
|--------------------|--------------------|
| `a`                | `click`            |
| `button`           | `click`            |
| `details`          | `toggle`           |
| `form`             | `submit`           |
| `input`            | `input`            |
| `input type=submit`| `click`            |
| `select`           | `change`           |
| `textarea`         | `input`            |

## 次回
さらに、ドキュメントを進めていきます。
イベントの種類についてもどこかでまとめられたらと思います。