clipboard-copy, copy-to-clipboard, ngclipboard, react-copy-to-clipboard, and vue-clipboard2 are npm packages that help developers implement copy-to-clipboard functionality in web applications. They abstract away browser inconsistencies and security restrictions around the Clipboard API, offering simple interfaces to copy text programmatically or via user interaction. While some are framework-agnostic utilities (clipboard-copy, copy-to-clipboard), others are tightly integrated with specific frontend frameworks like Angular (ngclipboard), React (react-copy-to-clipboard), or Vue.js (vue-clipboard2).
Copying text to the clipboard is a common UI requirement — think “copy invite link” buttons or “copy code snippet” actions. But browser security rules make this tricky: you can’t just write to the clipboard whenever you want. You need either a user gesture (like a click) or permission via the modern Async Clipboard API. The packages clipboard-copy, copy-to-clipboard, ngclipboard, react-copy-to-clipboard, and vue-clipboard2 all aim to simplify this, but they do it in very different ways depending on your stack and needs.
clipboard-copy – Element-First, Zero DependenciesThis package takes a DOM element and copies its text content (or a custom value) using the best available method. It’s designed to be called inside event handlers.
// clipboard-copy
import copy from 'clipboard-copy';
document.getElementById('copy-btn').addEventListener('click', async () => {
await copy('Hello, clipboard!');
console.log('Copied!');
});
It also supports passing a DOM element whose .textContent will be copied:
const el = document.querySelector('#secret-code');
await copy(el); // Copies el.textContent
Under the hood, it tries the modern navigator.clipboard.writeText() first, falling back to document.execCommand('copy') in older browsers.
copy-to-clipboard – Promise-Based, No DOM RequiredThis is a pure function that takes a string and returns a promise. No element reference needed.
// copy-to-clipboard
import copy from 'copy-to-clipboard';
async function handleCopy() {
try {
await copy('https://example.com/share?token=abc123');
alert('Link copied!');
} catch (err) {
console.error('Failed to copy', err);
}
}
It uses the same fallback strategy as clipboard-copy but exposes a cleaner async interface. Great when your copy logic lives in a service or utility file, not tied to a specific button.
ngclipboard – Angular Directive (Deprecated Pattern)This package provides an Angular directive that binds to a string value and triggers copy on click.
<!-- ngclipboard (Angular) -->
<button [ngClipboard]="'Text to copy'" (cbOnSuccess)="onCopied()">
Copy
</button>
However, the repository hasn’t been updated for Angular Ivy or recent versions. It relies on Renderer2 and manual event binding, and there’s no official support for standalone components or signals. Given its inactive status, avoid in new Angular projects.
react-copy-to-clipboard – React Component with State FeedbackThis wraps copy logic in a React component that manages success state for you.
// react-copy-to-clipboard
import { CopyToClipboard } from 'react-copy-to-clipboard';
function ShareButton() {
const [copied, setCopied] = useState(false);
return (
<CopyToClipboard text="invite@example.com" onCopy={() => setCopied(true)}>
<button>{copied ? 'Copied!' : 'Copy Email'}</button>
</CopyToClipboard>
);
}
It uses copy-to-clipboard under the hood but adds React-specific ergonomics. Note: it doesn’t use hooks internally (as of latest release), so it’s class-component friendly but slightly heavier than calling copy-to-clipboard directly in a useCallback.
vue-clipboard2 – Vue 2 Plugin with DirectiveFor Vue 2, this registers a global directive and a $copyText method.
// vue-clipboard2 (Vue 2)
// In main.js
import VueClipboard from 'vue-clipboard2';
Vue.use(VueClipboard);
Then in a component:
<template>
<button v-clipboard:copy="text" v-clipboard:success="onCopy">Copy</button>
</template>
<script>
export default {
data() {
return { text: 'Hello from Vue!' };
},
methods: {
onCopy() {
this.$message('Copied!');
}
}
};
</script>
But this package does not work with Vue 3. The Vue 3 ecosystem has moved toward composable functions, and this plugin hasn’t adapted. For Vue 3, skip this and use copy-to-clipboard inside a @click handler.
ngclipboard: Last published in 2018. No support for Angular 9+. Repository archived or inactive. Do not use in new projects.vue-clipboard2: Last update in 2020. Explicitly Vue 2 only. No Vue 3 compatibility. Avoid for Vue 3 apps.react-copy-to-clipboard: Actively maintained as of 2023, supports React 16–18, but doesn’t leverage modern hooks patterns.clipboard-copy and copy-to-clipboard: Both actively maintained, framework-agnostic, and support modern browsers with graceful fallbacks.All packages attempt to use navigator.clipboard.writeText() first (secure, async, requires HTTPS or localhost). If unavailable (e.g., Safari < 13.1, old Chrome), they fall back to the deprecated but widely supported document.execCommand('copy').
The fallback requires creating a temporary <textarea>, adding it to the DOM, selecting its content, and triggering execCommand. Both clipboard-copy and copy-to-clipboard handle this cleanly:
// Simplified fallback logic (used by both)
function fallbackCopyText(text) {
const textarea = document.createElement('textarea');
textarea.value = text;
textarea.style.position = 'fixed';
document.body.appendChild(textarea);
textarea.select();
try {
return document.execCommand('copy');
} finally {
document.body.removeChild(textarea);
}
}
Framework-specific packages inherit this behavior from their underlying utilities.
copy-to-clipboard if:async/await syntax and don’t need automatic UI feedback.clipboard-copy if:react-copy-to-clipboard if:useState boilerplate.copy-to-clipboard.ngclipboard and vue-clipboard2 in new projects because:💡 Pro Tip: In 2024, most apps can safely use the native
navigator.clipboard.writeText()directly if you control your browser support matrix. Only reach for a package if you need IE11 or old Safari support — and even then,copy-to-clipboardis the safest bet.
For new projects, default to copy-to-clipboard — it’s simple, well-maintained, and works everywhere. If you’re deep in React and love components, react-copy-to-clipboard is fine. But steer clear of ngclipboard and vue-clipboard2 unless you’re maintaining a legacy Angular or Vue 2 app with no upgrade path.
Remember: the clipboard is a user-facing feature. Always provide visual feedback (“Copied!”) and never copy without explicit user intent — browsers will block silent clipboard writes anyway.
Choose ngclipboard only if you’re working on an Angular application and want a directive-based approach that integrates with Angular’s template syntax. However, note that the package appears unmaintained and lacks support for modern Angular versions — consider using Angular’s built-in renderer or a lightweight alternative instead.
Choose clipboard-copy if you need a tiny, zero-dependency utility that works directly with DOM elements and supports both modern Clipboard API and legacy document.execCommand() fallbacks. It’s ideal for vanilla JavaScript projects or when you want minimal abstraction and full control over element selection and event handling.
Choose copy-to-clipboard if you prefer a promise-based, framework-agnostic function that copies text without requiring a DOM element reference. It’s well-suited for logic-heavy applications where clipboard operations are triggered from business logic rather than direct UI events, and you want clean async/await syntax.
Choose react-copy-to-clipboard if you’re building a React app and want a component that handles clipboard state (like success feedback) declaratively. It wraps the underlying copy logic in a render prop or child function pattern, making it easy to show UI changes after copying, though it adds a small layer of abstraction over simpler utility functions.
Choose vue-clipboard2 if you’re using Vue 2 and need a directive (v-clipboard) or programmatic API that fits naturally into Vue’s reactivity system. Be aware it is not compatible with Vue 3, and the project shows signs of abandonment — for new Vue 3 projects, use the native Clipboard API or a framework-agnostic utility.
Angularjs directive for clipboard.js by @zenorocha
You can get it on npm.
npm install ngclipboard --save
Or bower, too.
bower install ngclipboard --save
If you're not into package management, just download a ZIP file.
First, include angularjs and clipboard.js into your document.
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
<script src="https://cdn.rawgit.com/zenorocha/clipboard.js/master/dist/clipboard.min.js"></script>
Then Include ngclipboard.js.
<script src="dist/ngclipboard.min.js"></script>
Add ngclipboard dependency to your module
var myApp = angular.module('app', ['ngclipboard']);
Finally, add ngclipboard directive to the wanted html element.
<button class="btn" ngclipboard data-clipboard-text="Just because you can doesn't mean you should — clipboard.js">
Copy to clipboard
</button>
We're living a declarative renaissance, that's why we decided to take advantage of HTML5 data attributes for better usability.
A pretty common use case is to copy content from another element. You can do that by adding a data-clipboard-target attribute in your trigger element.
The value you include on this attribute needs to match another's element selector.
<!-- Target -->
<input id="foo" value="https://github.com/sachinchoolur/ngclipboard.git">
<!-- Trigger -->
<button class="btn" ngclipboard data-clipboard-target="#foo">
<img src="https://raw.githubusercontent.com/sachinchoolur/ngclipboard/HEAD/assets/clippy.svg" alt="Copy to clipboard">
</button>
Additionally, you can define a data-clipboard-action attribute to specify if you want to either copy or cut content.
If you omit this attribute, copy will be used by default.
<!-- Target -->
<textarea id="bar">Mussum ipsum cacilds...</textarea>
<!-- Trigger -->
<button class="btn" ngclipboard data-clipboard-action="cut" data-clipboard-target="#bar">
Cut to clipboard
</button>
As you may expect, the cut action only works on <input> or <textarea> elements.
Truth is, you don't even need another element to copy its content from. You can just include a data-clipboard-text attribute in your trigger element.
<!-- Trigger -->
<button class="btn" ngclipboard data-clipboard-text="Just because you can doesn't mean you should — clipboard.js">
Copy to clipboard
</button>
There are cases where you'd like to show some user feedback or capture what has been selected after a copy/cut operation.
That's why we fire custom events such as success and error for you to listen and implement your custom logic.
ngclipboard provides you two attributes called ngclipboard-success and ngclipboard-error to listen the clipboard events and implement your custom logic.
<button class="btn" ngclipboard ngclipboard-success="onSuccess(e);" ngclipboard-error="onError(e);" data-clipboard-text="Just because you can doesn't mean you should — clipboard.js">
Copy to clipboard
</button>
// You can still access the clipboard.js event
$scope.onSuccess = function(e) {
console.info('Action:', e.action);
console.info('Text:', e.text);
console.info('Trigger:', e.trigger);
e.clearSelection();
};
$scope.onError = function(e) {
console.error('Action:', e.action);
console.error('Trigger:', e.trigger);
}
For a live demonstration, open this site and just your console :)
This library relies on both Selection and execCommand APIs. The second one is supported in the following browsers.
![]() | ![]() | ![]() | ![]() | ![]() |
|---|---|---|---|---|
| 42+ ✔ | 41+ ✔ | 9+ ✔ | 29+ ✔ | 10+ ✔ |
When an occurence occurs where the execCommand copy/cut operations are not supported, it gracefully degrades because Selection is widely supported.
That means you can show a tooltip saying Copied! when success event is called and Press Ctrl+C to copy when error event is called because the text is already selected.
For a live demonstration, open this site with a non-supporting browser.
MIT License