【Rails7】JavaScript(+Stimulus)でクリップボードにコピーするボタンを実装してみた

表示されたテキストをボタンクリック一つでクリップボードにコピーしてくれる機能、あったら便利ですよね。

ということで、今どきのWebサービスでよく見かける以下のようなボタンを実装してみました。

今回の実装で用いたJSライブラリはStimulus。

Rails7でStimulus使って実装してきたいよー、という方の参考になれば幸いです。

目次

開発環境

  • Ruby 3.1.2
  • Ruby on Rails 7.0.3
  • Bootstrap 5.1.3
  • jsbundling-rails (1.0.3)
  • cssbundling-rails (1.1.1)
  • M1 Macbook Air 2020
  • mac OS Monterey (ver. 12.4)
  • ターミナル bash (Rosetta 2 使用

JS + Stimulusでクリップボードにコピーする方法

それでは順番に解説していきます。

フォームを作成する

まずは、テキストを表示させるためのフォームとコピーイベント発火用のボタン(以下コピーフィールド)を作成します。

CSS、およびアイコンはbootstrap5を使用しています。

<h2 class="mb-3">クリップボード↓</h2>
<div class="mb-3">
  URL: <input type="text" value="kobacchi.com" readonly>
  <a href="#" class="btn btn-secondary"><i class="bi bi-clipboard"></i> Copy to Clipboard</a>
</div>

Stimulusコントローラーを作成

以下のコマンドでStimulusコントローラーを作成します。

$ rails g stimulus コントローラー名

例)
$ rails g stimulus clipboard

上記のコマンドで、app/javascript/controllersディレクトリ以下にclipboard_controller.jsファイルが追加されているかと思います。

HTMLにdata属性を設定する

Stimulusコントローラー(target、action)とHTMLファイルを接続するために、コピーフィールドにdata属性を追加します。

追加するdata属性の種類は以下の3つです。

  1. data-controller
  2. data-action
  3. data-{controller}-target

Stimulusのdata属性の役割について詳しく知りたい方は公式マニュアルをご覧ください。

<h2 class="mb-3">クリップボード↓</h2>
<div data-controller="clipboard">
 <div class="mb-3">
   URL: <input data-clipboard-target="source" type="text" value="kobacchi.com" readonly>
   <a href="#" class="btn btn-secondary" 
               data-clipboard-target="copy_button" 
               data-action="clipboard#copy">
     <i class="bi bi-clipboard"></i> Copy to Clipboard
   </a>
 </div>
</div>

これで、Stimulusを動かす準備が整いました。

Stimulusコントローラーにターゲット、アクションを追加する

Stimulusコントローラーに要素のターゲットsource, copy_button、およびボタン(リンク)クリック時にテキストをクリップボードにコピーするためのアクションcopy()を追加します。

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

  copy(){
    // ↓ボタンクリック時にテキスト(this.sourceTarget.value)をクリップボードにコピーする
    navigator.clipboard.writeText(this.sourceTarget.value)
    // ↓コピー完了後にボタン(リンク)のテキストを上書きする
    this.copy_buttonTarget.innerHTML = '<i class="bi bi-clipboard-check"></i> Copied!!'
  }
}

これで完成です。

以下のような動作になればOKです。

複数のコピーフィールドを設置する場合

以下のように、複数のコピーフィールドを設置する場合についてみていきましょう。

先ほど作成したStimulusのcopy()アクションは再利用できるので、複数のコピーフィールドを設置する場合はコピーフィールド毎に新しいアクション(copy2(), copy3()など)を定義する必要はありません。

HTMLのコピーフィールドもvalueなどのテキスト以外はそのまま再利用できます。

上のような3つのコピーフィールドを設置する場合、HTMLは以下のようになります↓

<h2 class="mb-3">クリップボード↓</h2>
<!--  フィールド① -->
<div data-controller="clipboard">
 <div class="mb-3">
   URL: <input data-clipboard-target="source" type="text" value="kobacchi.com" readonly>
   <a href="#" class="btn btn-secondary" 
               data-clipboard-target="copy_button" 
               data-action="clipboard#copy">
     <i class="bi bi-clipboard"></i> Copy to Clipboard
   </a>
 </div>
</div>
<!--  フィールド② -->
<div data-controller="clipboard">
 <div class="mb-3">
   Blog: <input data-clipboard-target="source" type="text" value="こばっちブログ" readonly>
   <a href="#" class="btn btn-secondary" 
               data-clipboard-target="copy_button" 
               data-action="clipboard#copy">
     <i class="bi bi-clipboard"></i> Copy to Clipboard
   </a>
 </div>
</div>
<!--  フィールド③ -->
<div data-controller="clipboard">
 <div class="mb-3">
   PIN: <input data-clipboard-target="source" type="text" value="1234" readonly>
   <a href="#" class="btn btn-secondary" 
               data-clipboard-target="copy_button" 
               data-action="clipboard#copy">
     <i class="bi bi-clipboard"></i> Copy to Clipboard
   </a>
 </div>
</div>

各コピーフィールド毎にdata-controller属性を指定するのを忘れずに。

続いては、Stimulusコントローラーのcopy()アクションですが、copy()の引数にeventを渡してevent.preventDefault()を付け加えるだけでOKです。

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

  copy(event){
    event.preventDefault() // ←追加する
    navigator.clipboard.writeText(this.sourceTarget.value)
    this.copy_buttonTarget.innerHTML = '<i class="bi bi-clipboard-check"></i> Copied!!'
  }
}

これで、複数のコピーフィールドの設置が可能になりました。

参考資料

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

愛知の34歳。無職で暇になり始めたプログラミング(Ruby on Rails)の忘備録をまとめたブログです。最近は別にやりたいことができたのでプログラミングほぼやっていません。気が向いたらまた再開するかも。僕の日常はメインブログの方で更新しています。

コメント

コメントする

目次