ruang.work

Create click to copy using custom event with svelte

  • Avatar for Ilham Nuruddin Al Huda
Ilham Nuruddin Al Huda
•

8 min read

Share to Learn

In this tutorial, we will create “click to copy” feature by using custom event in Svelte.

in this tutorial we use TypeScript, so make sure to configure your project to support Typescript before starting.

It’s simple, just add lang="ts" is your script tag. 👍🏻

<script lang="ts">

First, let’s look at the basic Svelte skeleton code to create a text input and button to copy the text. i added on:copied to imagine how it would happen.

<script lang="ts">
let input: string = ``;
function clickToCopy(node: HTMLElement, target?: any) {
// implementasi custom event
}
function handleCopied() {
// implementasi aksi setelah berhasil menyalin teks
}
</script>
<div>
<input type="text" bind:value={input} />
<button use:clickToCopy={'#text'} on:copied={handleCopied}>
{text}
</button>
<pre id="text">{input}</pre>
</div>

In the code above, we create input to hold the text to be copied, clickToCopy to handle the coping action, and handleCopied to handle the action after successfully copying the text.

To create the “click to copy” feature with Svelte, we will use CustomEvent class. CustomEvent allows us to create events that can be captured by HTML elements.

async function copyText() {
let text = target ? document.querySelector(target)?.innerText : node.innerText
if (!text) return
try {
await navigator.clipboard.writeText(text)
node.dispatchEvent(
new CustomEvent('copied', {
bubbles: true,
})
)
} catch (error) {
node.dispatchEvent(
new CustomEvent('copyerror', {
bubbles: true,
detail: error,
})
)
}
}

In the copyText function, we start by retrieving the text of the HTML element to be copied. If no text is found, then we exit the function.

Then we try to copy the text to the clipboard using navigator.clipboard.writeText. If the copy is successful, we trigger the “copied” event using CustomEvent.

function clickToCopy(node: HTMLElement, target?: any) {
async function copyText() {
// implementasi copyText seperti di atas
}
node.addEventListener('click', copyText);
return {
destroy() {
node.removeEventListener('click', copyText);
},
};
}

In the clickToCopy function, we add an event listener for the click event on the HTML element that will copy the text. If the click event is detected, then we execute the copyText function.

function handleCopied() {
text = 'Copied'
window.setTimeout(() => {
text = 'Click to Copy'
}, 2000)
}

In the handleCopied function, we change the text on the button to “Copied” after successfully copying the text. After 2 seconds, the text will be changed back to “Click to Copy”.

Here are the codes of all the implemented codes:

<script lang="ts">
let input: string = ``;
function clickToCopy(node: HTMLElement, target?: any) {
async function copyText() {
let text = target ? document.querySelector(target)?.innerText : node.innerText;
if (!text) return;
try {
await navigator.clipboard.writeText(text);
node.dispatchEvent(
new CustomEvent('copied', {
bubbles: true,
})
);
} catch (error) {
node.dispatchEvent(
new CustomEvent('copyerror', {
bubbles: true,
detail: error,
})
);
}
}
node.addEventListener('click', copyText);
return {
destroy() {
node.removeEventListener('click', copyText);
},
};
}
function handleCopied() {
text = 'Copied';
window.setTimeout(() => {
text = 'Click to Copy';
}, 2000);
}
</script>
<div>
<input type="text" bind:value={input} />
<button use:clickToCopy={'#text'} on:copied={handleCopied}>
{text}
</button>
<pre id="text">{input}</pre>
</div>

Pretty simple? What do you think?