Copy to Clipboard with Phoenix LiveView

Illustration of a server reaching into your laptop and writing to your clipboard.
Image by Annie Ruygt

In this article we show how a LiveView and a snippet of JS can make it easier for users to copy an important value to their clipboard. Fly.io is a great place to run your Phoenix LiveView applications! Check out how to get started!

Problem

When you need to make sure a user copies an important string of text, don’t let their mouse and keyboard stand in the way. Give them a button to press so they don’t need to manually move a cursor around.

But how might you do this with LiveView? It’s not like our servers have access to the user’s clipboard?

Solution

First lets make our copy button. Put this wherever you need it!

<button phx-click={JS.dispatch("phx:copy", to: "#control-codes")}>  
  ๐Ÿ“‹
</button>

This uses the Phoenix.LiveView.JS.dispatch/2 function to dispatch a JavaScript Custom Event to the element matching your selector. In this case the #control-codes element should contain the text we want to copy as its value.

<input type="text" id="control-codes" value={@control-codes} />

Now lets wire up a little bit of javascript and append it to the bottom of our assets/js/app.js:

window.addEventListener("phx:copy", (event) => {
let text = event.target.value; // Alternatively use an element or data tag!
  navigator.clipboard.writeText(text).then(() => {
    console.log("All done!"); // Or a nice tooltip or something.
  })
})

And we’ve done it! We have a simple generic handler for any and all copy functionality. If we add some CSS and dress it up, we could have something like this.

It’s worth pointing out that this code runs 100% on the client. The JS.dispatch is essentially writing the JavaScript required for us to create the event and if we take a peak in the inspector we can see it!

That’s pretty neat if you ask me!

Client Hooks

This is not the only way to accomplish the JavaScript integration. We could use the Client Hooks functionality. First, we create our hook to handle the copy.

let Hooks = {}

Hooks.Copy = {
  mounted() {
    let { to } = this.el.dataset;
    this.el.addEventListener("click", (ev) => {
      ev.preventDefault();
      let text = document.querySelector(to).value
      navigator.clipboard.writeText(text).then(() => {
        console.log("All done again!")
      })
    });
  },
}

let liveSocket = new LiveSocket("/live", Socket, {hooks: Hooks, ...})

Now our button should look like below. Note that all Hooks need unique id’s to work properly.

<button id="copy" data-to="#control-codes" phx-hook="Copy">
  ๐Ÿ“‹
</button>

This results in the same functionality with slightly more ceremony to accomplish it. We achieved the same goal: client-side only code handles the click and copying for us!

Discussion

We could also imagine using this for all kinds of simple and commonly used JavaScript while having a shared interface to do it. Maybe you want to play a sound or focus an element, it is just JavaScript so the browser is the limit!

That’s it! We walked through two approaches to copying text to a user’s clipboard and hopefully learned a little bit about how Phoenix is helping write our JavaScript for us.

Fly.io โค๏ธ Elixir

Fly.io is a great way to run your Phoenix LiveView app close to your users. It’s really easy to get started. You can be running in minutes.

Deploy a Phoenix app today! โ†’