Interacting with the (browser) Clipboard from LWC
You are correct that clipboard
on secure
navigator is not available.
So, as a work around, get the details you need from variables in javascript and set it in an input, then copy that. Here is example:
HTML:
<div style="width: 20rem;">
<lightning-card>
<h3 class="title" slot="title">
<a href="javascript:void(0);">Day {day.id}</a>
</h3>
<lightning-button-menu icon-size="xx-small" alternative-text="Actions" slot="actions">
<lightning-menu-item value="Copy" label="Copy" onclick={copyDay}></lightning-menu-item>
</lightning-button-menu>
</lightning-card>
</div>
<input disabled class="my-class" style="position:fixed;top:-5rem;height:1px;width:10px;"></input>
JS:
@api day = { id: '123', name: 'my_day', label: 'My Day' };
copyDay = function() {
console.log(`Entry ${this.day.id}!`);
this.doCopy();
};
doCopy = function() {
let content = this.day;
let inp = this.template.querySelector('.my-class');
inp.disabled = false;
inp.value = JSON.stringify(content);
inp.select();
document.execCommand('copy');
inp.disabled = true;
console.log(`copied ${this.day.id}`);
};
Input will not work if not visible atleast as a tiny dot (cannot use slds-hide or width and height cannot be 0). Height 1 and width 10 is the best I was able to achieve. While copying remove disable and after copying disable it.
Quite useful thread! I've put all your ideas in a Javascript module in this repository so that can import the it in any of your LWC's. Also, I found that the input element doesn't pick up line breaks, so you'll see that I'm creating a text area instead. I've also created a small component to demo how it works here.
Hopefully it is useful to you all.
In summary, the component would look like this:
const copyTextToClipboard = (content) => {
// Create an input field with the minimum size and place in a not visible part of the screen
let tempTextAreaField = document.createElement('textarea');
tempTextAreaField.style = 'position:fixed;top:-5rem;height:1px;width:10px;';
// Assign the content we want to copy to the clipboard to the temporary text area field
tempTextAreaField.value = content;
// Append it to the body of the page
document.body.appendChild(tempTextAreaField);
// Select the content of the temporary markup field
tempTextAreaField.select();
// Run the copy function to put the content to the clipboard
document.execCommand('copy');
// Remove the temporary element from the DOM as it is no longer needed
tempTextAreaField.remove();
}
export { copyTextToClipboard };
And it would be used like this:
import { copyTextToClipboard } from 'c/copyTextToClipboard';
export default class CopyToClipboardBtn extends LightningElement {
handleClick() {
copyTextToClipboard('Copy this!');
}
}