Michael Anhari

Copy text to a user’s clipboard using Stimulus.js

Top down view of a clipboard holding a printed spreadsheet on top of wooden planks

Stimulus.js is a lightweight approach for adding some interactivity to server-rendered applications using templating languages like ERB in Rails or EEX in Phoenix.

Let's try using it to build a button for storing information into the user's system clipboard.

A quick intro to Stimulus.js

A whirlwind tour of Stimulus.js is in order. Essentially, Stimulus works by wiring up DOM elements to JavaScript classes that it calls controllers using data attributes.

  • data-controller is used to wire up a Stimulus controller
  • data-[controller-name-here]-target is used to wire up elements of importance that are inside the data-controller element
  • data-action is used to wire up events to methods in our Stimulus controllers

Adding our markup

Let's add the HTML (in our case we'll be writing ERB) and pretend that were adding a button to copy the current branch name on GitHub.

<div data-controller="clipboard" class="mr-2">
  <%= hidden_field_tag(
        :branch,
        @current_branch.name,
        data: { clipboardTarget: "source" },
        readonly: true
      )
  %>
  <button data-action="clipboard#copy">
    Copy branch
  </button>
</div>

In this case, we're wiring up our div to our Stimulus controller defined in clipboard_controller.js, attaching a hidden input as our source, and wiring up our button to the copy() method in our controller.

Adding our Stimulus controller

In a file named clipboard_controller.js add the following:

import { Controller } from "stimulus";

export default class extends Controller {
  // define our targets in our controller
  static get targets() {
    return ["source"];
  }

  // define our copy action
  copy() {
     alert("hello, this is the clipboard copy action!")
  }
}

With this is in place, our clipboard controller should be successfully wired up. Now we just need to make it useful!

Leveraging the web's Clipboard API

I was able to find the Web API for writing to a user's clipboard on MDN.

import { Controller } from "stimulus";

export default class extends Controller {
  // define our targets in our controller
  static get targets() {
    return ["source"];
  }

  // define our copy action
  copy() {
    navigator.clipboard.writeText(this.sourceTarget.value);
  }
}

Since we added the data-clipboard-target="source" attribute to our hidden input, it is now available to us in our Stimlus controller using this.sourceTarget. In the example above, we're grabbing the value of our hidden input, which is currently set to @current_branch.name in our template.

Wrap-up

That should do it! There's room for improvement for our little feature here. We're not providing any user feedback that copying to the clipboard was successful, and maybe the clipboard-copy heroicon SVG would look nice here as well. But I'll leave that to you :)

Hope you enjoyed this whirlwind introduction for using Stimulus.js to make the lives of your users just a bit easier. Cheers!

Newsletter

I'm working on sending out a weekly newsletter. I'll make it as easy as possible to unsubscribe at any time.