We can't find the internet
Attempting to reconnect
Something went wrong!
Hang in there while we get back on track
First, start with defining a new LiveView component, for example in your lib/my_app/core_components.ex
file. The component looks like this:
defmodule MyAppWeb.CoreComponents do
# Standard code should be here
attr :value, :string, required: true
def copy_to_clipboard(assigns) do
assigns = assigns |> assign(:uuid, Ecto.UUID.generate())
~H"""
<textarea class="hidden" id={@uuid}>{@value}</textarea>
<a phx-click={JS.dispatch("phx:copy", to: "##{@uuid}")} class="cursor-pointer">
📋 copy to clipboard
</a>
"""
end
end
The component takes one single attribute which is the value to copy to the clipboard.
The component itself results in two separate HTML items.
A textarea
element which contains the value to copy to the clipboard. It's hidden as the end user doesn't need to see it. I've used a textarea
element as that can hold a lot of data and will preserve newlines. We also assign a unique id to the textarea as potentially, we can have multiple copies of this element on the page, and each one should know extactly what to copy to the clipboard.
We also have a a
element which uses the JS.dispatch/2
function to dispatch the phx:copy
event, passing along a parameter called to
which specifies the element ID where the data can be found. As this is a query selector, we prepend it with a #
to indicate that we query on the id of the element. As the link doesn't have a href
attribute, we also add the Tailwind CSS class cursor-pointer
to show the proper cursor when hovering over the item.
So far, so good, now it's time to implement the actual copy functionality. This means we need to handle the phx:copy
event somewhere. Head over to the assets/js/app.js
file and add the following code:
window.addEventListener("phx:copy", (event) => {
let text = event.target.value;
navigator.clipboard.writeText(text).then(() => {
console.log("All done!"); // Or a nice tooltip or something.
});
});
This takes value of the target of the event (the text to copy) and uses the navigator.clipboard.writeText
function to write it to the clipboard.
To use the component, it's as simple as:
<.copy_to_clipboard value={@value} />
I got the inspiration for doing this from here.
If this post was enjoyable or useful for you, please share it! If you have comments, questions, or feedback, you can email my personal email. To get new posts, subscribe use the RSS feed.