LoginSignup
1
0

More than 5 years have passed since last update.

Hyperstackでbrowser非表示のmodelの属性値をclipboardへコピー

Last updated at Posted at 2019-06-08

親コンポーネントで#find_byで取得したmodelをparam に受け取って、リンククリック時にclipboardへコピーしたい。

  • TEXTAREAをマウントしてmodelの属性値をvalue(またはdefaultValue)に入れておいても、TEXTAREAを style で隠すと、element.select か copy がうまく動作しなかった。

  • リンククリック時に TEXTAREA要素を追加、select、copy、removeするのでは、属性値が取得できなかった。

解決法

catmandoさんから、コメント欄に解決法をいただきました。ありがとうございます!
@OneUser.name.loaded? を利用して、ロードが完了してからリンクが表示されるようにします。

class ClipTest < HyperComponent
  param :one_user

  render(DIV) do
# 'name'がロードされるまで空の文字列を表示する
    return '' unless @OneUser.name.loaded?

    A(href: '') { '名前をclip' }
      .on(:click) do |evt|
        evt.prevent_default
        copy_to_clipboard(@OneUser.name)
      end
  end

  def copy_to_clipboard(text_to_copy)
    supported = $$.document.queryCommandSupported('copy')
    puts("copy to clipboard is #{'not ' unless supported}supported.")
    return unless supported

    textarea = $$.document.createElement('textarea')
    copy_from = $$.document.body.appendChild(textarea)
    copy_from.textContent = text_to_copy

    puts("copy to clipboard : #{copy_from.textContent}")
    copy_from.select
    $$.document.execCommand('copy')
    copy_from.remove
  end
end

試行錯誤

textarea要素をマウントしておく方法では、display: 'none' で表示しないようにしておくと、select か copyがうまく動作しなかった。

class ClipTest < HyperComponent
  param :one_user

  render(DIV) do
    A(href: '') { '名前をclip' }
      .on(:click) do |evt|
        evt.prevent_default
        copy_to_clipboard(textarea_id)
      end

    TEXTAREA(id: textarea_id, 
             defaultValue: @OneUser.name,
             style: { display: 'none'})   # 隠してマウントしておく
  end

  def textarea_id
    "textarea-#{@OneUser.id}"
  end

  def copy_to_clipboard(element_id)
    supported = $$.document.queryCommandSupported('copy')
    puts("copy to clipboard is #{'not ' unless supported}supported.")
    return unless supported

    copy_from = $$.document.getElementById(element_id)
    puts("copy to clipboard : #{copy_from.textContent}")
    copy_from.select
    $$.document.execCommand('copy')
  end

これでリンクをクリックすると、puts で "copy to clipboard : <@OneUser.nameの値>" が正常にコンソールに出力されるのだが、クリップボードにはコピーされない。

TEXTAREAの styleを、{ display: 'block' }にした場合は、クリップボードへのコピーが正常にできた。

after_mount で属性をロードさせておいて、リンククリック時にTEXTAREA要素を追加。

class ClipTest < HyperComponent
  param :one_user

  after_mount do
    @OneUser.name
  end

  render(DIV) do
    A(href: '') { '名前をclip' }
      .on(:click) do |evt|
        evt.prevent_default
        copy_to_clipboard(@OneUser.name)
      end
  end

  def copy_to_clipboard(text_to_copy)
    supported = $$.document.queryCommandSupported('copy')
    puts("copy to clipboard is #{'not ' unless supported}supported.")
    return unless supported

    textarea = $$.document.createElement('textarea')
    copy_from = $$.document.body.appendChild(textarea)
    copy_from.textContent = text_to_copy

    puts("copy to clipboard : #{copy_from.textContent}")
    copy_from.select
    $$.document.execCommand('copy')
    copy_from.remove
  end
end

after_mount がないと、copy_to_clipboardの puts で "copy to clipboard : " とだけ出力された。引数のtext_to_copy に属性値が渡っていない。
この方法では、nameがロードされる前にリンクがクリックされた場合に問題が起きる。

1
0
2

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
1
0