0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Hotwire ハンドブック 日本語訳Advent Calendar 2022

Day 13

Stimulus 3: リアルなものを構築する

Last updated at Posted at 2022-12-12

この記事はGoogle翻訳の結果を編集したものです。

最初のコントローラーを実装し、StimulusがHTMLをJavaScriptに接続する方法を学びました。 それでは、Basecampからコントローラーを再作成して、実際のアプリケーションで使用できるものを見てみましょう。

DOMクリップボードAPIのラッピング

BasecampのUIには次のようなボタンが散在しています。

bc3-clipboard-ui.png

これらのボタンのいずれかをクリックすると、BasecampはURLや電子メー アドレスなどのテキストをクリップボードにコピーします。

WebプラットフォームにはシステムクリップボードにアクセスするためのAPIがありますが、必要なことを行うHTML要素はありません。"クリップボードにコピー"ボタンを実装するにはJavaScriptを使用する必要があります。

コピーボタンの実装

PINを生成して他のユーザーにアクセスを許可できるアプリがあるとします。生成されたPINをボタンと一緒に表示して、簡単に共有できるようにクリップボードにコピーできれば便利です。

public/index.htmlを開き<body>の内容をボタンのラフスケッチに置き換えます。

<div>
  PIN: <input type="text" value="1234" readonly>
  <button>Copy to Clipboard</button>
</div>

コントローラーのセットアップ

次にsrc/controllers/clipboard_controller.jsを作成し、空のメソッドcopy()を追加します。

// src/controllers/clipboard_controller.js
import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
  copy() {
  }
}

次に外側の<div>data-controller="clipboard"を追加します。この属性が要素に表示されるたびに、Stimulusはコントローラーのインスタンスを接続します。

<div data-controller="clipboard">

ターゲットの定義

クリップボードAPIを呼び出す前にその内容を選択できるように、テキストフィールドへの参照が必要です。テキストフィールドにdata-clipboard-target="source"を追加します。

PIN: <input data-clipboard-target="source" type="text" value="1234" readonly>

コントローラーにターゲット定義を追加して、テキストフィールド要素にthis.sourceTargetとしてアクセスできるようにします。

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

  // ...
}

静的ターゲットラインとは何ですか?

Stimulusがコントローラークラスをロードするとき、targetと呼ばれる静的配列でターゲット名の文字列を探します。配列内のターゲット名ごとにStimulusは3つの新しいプロパティをコントローラーに追加します。ここで、"source"ターゲット名は次のプロパティになります。

  • this.sourceTargetはコントローラーのスコープ内の最初のsourceターゲットに評価されます。sourceターゲットがない場合、プロパティにアクセスするとエラーがスローされます。
  • this.sourceTargetsは、コントローラーのスコープ内のすべてのsourceターゲットの配列に評価されます。
  • this.hasSourceTargetsourceターゲットがある場合はtrueに評価され、そうでない場合はfalseに評価されます。

ターゲットの詳細についてはリファレンスドキュメントを参照してください。

アクションの接続

これでコピーボタンを接続する準備が整いました。

ボタンをクリックしてコントローラーのcopy()メソッドを呼び出す必要があるため、data-action="clipboard#copy"を追加します。

<button data-action="clipboard#copy">Copy to Clipboard</button>

一般的なイベントには省略形のアクション表記があります

アクション記述子からclick->を省略したことに気付いたかもしれません。これはStimulusがクリックを<button>要素のアクションのデフォルトイベントとして定義しているためです。

他の特定の要素にもデフォルトのイベントがあります。 完全なリストは次のとおりです。

要素 デフォルトイベント
a click
button click
details toggle
form submit
input input
input type=submit click
select change
textarea input

最後にcopy()メソッドで入力フィールドの内容を選択し、クリップボードAPIを呼び出します。

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

ブラウザにページをロードし、コピーボタンをクリックします。 次にテキストエディターに戻って貼り付けます。PIN1234が表示されます。

Stimulusコントローラーは再利用可能

これまで一度に1つのコントローラーのインスタンスがページ上にある場合に何が起こるかを見てきました。

ページ上にコントローラーの複数のインスタンスが同時に存在することは珍しくありません。たとえばPINのリストを表示し、それぞれに独自のコピーボタンを表示したい場合があります。

私たちのコントローラーは再利用可能です。テキストの一部をクリップボードにコピーする方法を提供したいときはいつでも、必要なのはページに適切な注釈を付けてマークアップすることだけです。

ページに別のPINを追加してみましょう。<div>をコピーして貼り付け、2つの同一のPINフィールドが存在するようにし、2番目のvalue属性を変更します。

<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フィールドをもう1つ追加しましょう。 今回はボタンの代わりにコピーリンクを使用します。

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

Stimulusでは適切なdata-action属性を持っている限り、必要なあらゆる種類の要素を使用できます。

この場合、リンクをクリックするとブラウザーもリンクのhrefをたどることになることに注意してください。アクションでevent.preventDefault()を呼び出すことで、このデフォルトの動作をキャンセルできます。

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

同様にsourceターゲットは<input type="text">である必要はありません。コントローラーはvalueプロパティとselect()メソッドを持つことだけを想定しています。 つまり、代わりに<textarea>を使用できます。

PIN: <textarea data-clipboard-target="source" readonly>3737</textarea>

まとめと次のステップ

この章ではブラウザーAPIをStimulusコントローラーにラップする実際の例を見てきました。コントローラーの複数のインスタンスが一度にページに表示される方法を確認し、アクションとターゲットがHTMLとJavaScriptの疎結合を維持する方法を調べました。

次にコントローラーの設計を少し変更するだけで、より堅牢な実装につながる方法を見てみましょう。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?