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!');
    }
}