How to copy to clipboard in Vue 3

Jamie Curnow
3 min readDec 16, 2020

Copy any text to the clipboard in Vue 3 with the new Vue composition API.

Photo by Kelly on Unsplash

TL;DR: Use vue-clipboard3 (I maintain this package)

Today I needed to copy some text to the clipboard in my new Vue app where I’m using Vue 3 and the composition api.

I didn’t want to use a Vue directive as this seems a little messy and not so declarative, and the existing solutions either don’t work in Vue 3, don’t have good typescript support, are used as a Vue plugin binding to ‘this’ or are a hack of a Vue 2 solution.

So I set about writing a new composable that uses the trusted clipboard.js under the hood, is fully typed, is simple and has no side effects, is declarative and easy to use, and follows the spirit of Vue 3 and the composition API.

It turned out to be extremely easy to make! I just installed clipboard.js and it’s types:

$ yarn add clipboard
$ yarn add --dev @types/clipboard

And make a single composable file

// composables/useClipboard.tsimport Clipboard from 'clipboard'interface Options {
/** Fixes IE by appending element to body */
appendToBody: boolean
}
export default (opts?: Options) => {
// default appendToBody true
const appendToBody = opts?.appendToBody === undefined ? true : opts.appendToBody
return {
toClipboard(text: string, container?: HTMLElement) {
return new Promise((resolve, reject) => {
// make fake element
const fakeEl = document.createElement('button')
// setup a new Clipboard.js
const clipboard = new Clipboard(fakeEl, {
text: () => text,
action: () => 'copy',
container: container !== undefined ? container : document.body
})
clipboard.on('success', (e) => {
clipboard.destroy()
resolve(e)
})
clipboard.on('error', (e) => {
clipboard.destroy()
reject(e)
})
// appendToBody fixes IE
if (appendToBody) document.body.appendChild(fakeEl)
// simulate click
fakeEl.click()
// remove from body if appended
if (appendToBody) document.body.removeChild(fakeEl)
})
}
}
}

Then in my Vue component I use it like this (simplified version):

<template lang="html">
<button @click="copy">Copy!</button>
</template>

<script lang="ts">
import { defineComponent } from '@vue/composition-api'
import useClipboard from '~/composables/useClipboard'

export default defineComponent({
setup() {
const { toClipboard } = useClipboard()

const copy = async () => {
try {
await toClipboard('Any text you like')
console.log('Copied to clipboard')
} catch (e) {
console.error(e)
}
}

return { copy }
}
})
</script>

Made something useful? Open-source it!

I figured this may be useful to a lot of people as we transition from Vue 2 to Vue 3 and the composition API. So I open-sourced it!

Now you can simply:

$ yarn add vue-clipboard3

And

import useClipboard from 'vue-clipboard3'

Check out the repo and examples here:

And if you find any problems or have any feature requests, drop me an issue on the repo:

Happy clipboarding! 📋

Support your creators!

If you found this story useful and would like me to keep writing useful content, please consider supporting me on Patreon 🤗

--

--

Jamie Curnow

I am a javascript developer living in beautiful Cornwall, UK. Ever curious, always learning.