親コンポーネントで#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がロードされる前にリンクがクリックされた場合に問題が起きる。