Cross-Environment Clipboard Copy Implementation for Vue
Bind a click handler to your target element, passing the text string you want to duplicate during invocation.
Clipboard API Overview
The modern navigator.clipboard API provides a promise-based, secure way to interact with system clipboard data:
| Method | Purpose |
|---|---|
read() |
Retrieves arbitrary clipboard content (supports images, files, text) |
readText() |
Fetches plain text content exclusively from the system clipboard |
write() |
Writes mixed data types (text, images) to the system clipboard |
writeText() |
Simplifies plain text clipboard insertion with a single call |
Initial Plain Text Copy Function
async function performTextCopy(targetText) {
return await navigator.clipboard.writeText(targetText);
}
Comon Deployment Error
After local HTTPS/localhost testing, many teams encounter this issue on internal IP staging environments:
TypeError: Cannot read properties of undefined (reading 'writeText')
Root Cause Analysis
The navigator.clipboard API is restricted to secure contexts — pages served over HTTPS, localhost, or file:// URLs in some browsers. Internal IP addresses (like http://192.168.1.100) fall out side this scope, disabling the API entirely.
Compatibility-First Fix
Combine secure context detection with a fallback to the deprecated but widely supported document.execCommand('copy') method:
- Check for valid
navigator.clipboardand active secure context - Use the modern API first for better performance and security
- Fall back to a temporary off-screen
<textarea>element when needeed
import { ElMessage } from 'element-plus'; // Replace with your UI library toast
async function duplicateLink(linkValue) {
if (navigator.clipboard && window.isSecureContext) {
try {
await navigator.clipboard.writeText(linkValue);
ElMessage.success('Link copied to clipboard!');
return true;
} catch (err) {
console.error('Secure clipboard copy failed:', err);
}
}
// Fallback for non-secure contexts
const tempInput = document.createElement('textarea');
tempInput.value = linkValue;
tempInput.style.position = 'absolute';
tempInput.style.left = '-9999px';
tempInput.style.top = '-9999px';
tempInput.setAttribute('readonly', '');
document.body.appendChild(tempInput);
tempInput.focus();
tempInput.select();
tempInput.setSelectionRange(0, tempInput.value.length);
try {
const copySuccess = document.execCommand('copy');
if (copySuccess) {
ElMessage.success('Link copied to clipboard!');
} else {
ElMessage.error('Copy failed. Please select and copy manually.');
}
return copySuccess;
} catch (fallbackErr) {
console.error('Fallback copy method failed:', fallbackErr);
ElMessage.error('Copy failed. Please select and copy manually.');
return false;
} finally {
document.body.removeChild(tempInput);
}
}
Quick Reference for document.execCommand
While deprecated, document.execCommand still works across most browsers for basic text operations. It accepts three parameters:
commandId: String identifier for the desired actionshowUI: Boolean to enable/disable native dialogsvalueArgument: Optional dynamic input for commands requiring it
Basic Action Examples
<input type="button" value="Cut Selection" onclick="document.execCommand('Cut')">
<input type="button" value="Copy Selected" onclick="document.execCommand('Copy')">
<input type="button" value="Paste Content" onclick="document.execCommand('Paste')">
<input type="button" value="Undo Last Edit" onclick="document.execCommand('Undo')">
<input type="button" value="Delete Highlighted" onclick="document.execCommand('Delete')">
<input type="button" value="Toggle Bold" onclick="document.execCommand('Bold')">
<input type="button" value="Toggle Italic" onclick="document.execCommand('Italic')">
<input type="button" value="Toggle Underline" onclick="document.execCommand('Underline')">
<input type="button" value="Stop Page Load" onclick="document.execCommand('stop')">
<input type="button" value="Save Page" onclick="document.execCommand('SaveAs')">
Reusable Helper Functions
// Copy from a specific text area
function copyFromEditor(editorId) {
const editor = document.getElementById(editorId);
if (!editor) return;
editor.select();
document.execCommand('Copy');
}
// Paste into a target input
function pasteToTarget(targetId) {
const target = document.getElementById(targetId);
if (!target) return;
target.focus();
document.execCommand('Paste');
}
// Create hyperlink with custom URL
function addCustomHyperlink(url = 'https://example.com') {
document.execCommand('CreateLink', false, url);
}
// Change selected text foreground color
function setTextColor(colorCode) {
document.execCommand('ForeColor', false, colorCode);
}
// Toggle ordered/unordered lists
function toggleList(listType = 'InsertUnorderedList') {
document.execCommand(listType);
}