Copy Directive
The v-copy
directive is used to copy text to the clipboard. It is useful for copying text from a <textarea>
, <input>
or any other element.
Usage
Lorem ipsum dolor sit amet consectetur adipisicing elit. Libero autem fugiat dolorum, aperiam repellat eos ipsam obcaecati modi, similique harum dignissimos reiciendis cum, nobis delectus soluta ut quae! Nobis, explicabo.
View Code
<template>
<div class="w-full bg-gray-50 dark:bg-zinc-800 rounded-3xl p-5">
<textarea
v-model="text"
class="w-full p-2 resize-none h-24 rounded-2xl bg-zinc-100 dark:bg-zinc-700"
></textarea>
<button
v-copy.lowercase="text"
@copied="handleCopy"
@copyerror="handleCopyError"
class="px-4 py-2 bg-indigo-600 text-white rounded-lg"
>
{{ btnText }}
</button>
<p id="elem">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Libero autem
fugiat dolorum, aperiam repellat eos ipsam obcaecati modi, similique harum
dignissimos reiciendis cum, nobis delectus soluta ut quae! Nobis,
explicabo.
</p>
<button
v-copy:id="'elem'"
@copied="handleCopyPara"
class="px-4 py-2 bg-indigo-600 text-white rounded-lg"
>
{{ elemBtn }}
</button>
</div>
</template>
<script setup>
import { ref } from "vue";
const text = ref(null);
const btnText = ref("Copy");
const elemBtn = ref("Copy paragraph");
const handleCopy = () => {
btnText.value = "Copied";
setTimeout(() => {
btnText.value = "Copy";
}, 1500);
console.log("Text copied successfully");
};
const handleCopyPara = () => {
elemBtn.value = "Copied";
setTimeout(() => {
elemBtn.value = "Copy paragraph";
}, 1500);
console.log("Text copied successfully");
};
const handleCopyError = () => {
btnText.value = "Error";
setTimeout(() => {
btnText.value = "Copy";
}, 1500);
console.error("Error copying text");
};
</script>
Dynamic Content
<template>
<div>
<textarea v-model="text"></textarea>
<button v-copy="text">Copy</button>
</div>
<div>
<input v-model="text2" />
<button v-copy="text2">Copy</button>
</div>
</template>
Arguments
The v-copy
directive accepts only one argument id
. The id
argument is used to copy the inner content of an element by it's id.
Argument | Description |
---|---|
id | Copy the element's inner content by it's id |
id
<template>
<div>
<p id="elemId">
This content will be copied when you click the button, it is being copied
by id
</p>
<button v-copy:id="'elemId'">Copy</button>
</div>
</template>
Modifiers
The v-copy
directive accepts two modifiers uppercase
, lowercase
, camelcase
and pascalcase
. The uppercase
modifier is used to convert the copied text to uppercase, the lowercase
modifier is used to convert the copied text to lowercase, the capitalize
modifier is used to convert the copied text to capitalize, and the capitalizeAll
modifier is used to convert the copied text to capitalize all.
Modifier | Description |
---|---|
uppercase | Convert the copied text to uppercase |
lowercase | Convert the copied text to lowercase |
capitalize | Convert the copied text to capitalize |
capitalizeAll | Convert the copied text to capitalize all |
uppercase
<template>
<div v-copy.uppercase>
Lorem ipsum dolor sit, amet consectetur adipisicing elit.
</div>
</template>
Source Code
async function copyTextToClipboard(textToCopy, el) {
try {
await navigator.clipboard.writeText(textToCopy);
el.dispatchEvent(new Event("copied"));
} catch (error) {
el.dispatchEvent(new Event("copyerror"));
}
}
const applyModifiers = (text, modifiers) => {
let modifiedText = text;
if (modifiers.uppercase) {
modifiedText = modifiedText.toUpperCase();
} else if (modifiers.lowercase) {
modifiedText = modifiedText.toLowerCase();
} else if (modifiers.capitalize) {
modifiedText = modifiedText.charAt(0).toUpperCase() + modifiedText.slice(1);
} else if (modifiers.capitalizeAll) {
modifiedText = modifiedText
.split(" ")
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
.join(" ");
}
return modifiedText;
};
const clickCopyToClipboard = async (el, textToCopy, modifiers) => {
const modifiedText = applyModifiers(textToCopy, modifiers);
await copyTextToClipboard(modifiedText, el);
};
const handleCopy = (el, binding) => {
let textToCopy;
if (binding.arg === "id") {
const elem = document.getElementById(binding.value);
if (elem) {
textToCopy = elem.innerText;
}
} else {
textToCopy = binding.value;
}
const clickHandler = () =>
clickCopyToClipboard(el, textToCopy, binding.modifiers);
el.addEventListener("click", clickHandler);
// Save the reference to the click handler for removal during the update
el.clickCopyToClipboard = clickHandler;
};
export const vCopy = {
mounted(el, binding) {
handleCopy(el, binding);
},
updated(el, binding) {
el.removeEventListener("click", el.clickCopyToClipboard);
handleCopy(el, binding);
},
unmounted(el) {
// Remove the click event listener when the directive is unmounted
el.removeEventListener("click", el.clickCopyToClipboard);
},
};