Copy url to clipboard via button click in a vuejs component
Asked Answered
P

9

28

I have following component, and I would like to have a button that copies the link_url to the clipboard on click.

I have javascript code that works when selecting an id, however the links do not have an id. Can I accomplish the selection of the a-tag via refs in the component itself, or what would be the best way to get this done.

I was also thinking about generating an a-tag with the this.link_url in the copyURL() dynamically but I guess that would be very dirty.. I am looking for the vuejs way.

<template>
  <li class="list-group-item">
    <a :href="link_url" 
         class="text-dark" 
         target="_blank" 
         rel="noopener noreferrer">{{ link_name }}</a>
    <button @click="copyUrl">copy url from a tag</button>
  </li>      
</template>

<script>
export default {
  props: ["link_url", "link_name"],
  methods: {
    copyURL() {
      var Url = document.getElementById('myid'); /*GET vuejs el reference here (via $ref) but how?*/
      Url.innerHTML = window.location.href;
      console.log(Url.innerHTML)
      Url.select();
      document.execCommand("copy");
    }
  }
}
</script>

<style>
</style>
Pleasure answered 6/11, 2019 at 15:50 Comment(0)
C
16

If you need to use vuejs ref add it as attribute

<a :href="link_url" class="text-dark" target="_blank" rel="noopener noreferrer" ref="mylink">
    {{ link_name }}
</a>

and use it in your method in the following way:

  methods: {
    copyURL() {
      var Url = this.$refs.mylink;
      Url.innerHTML = window.location.href;
      console.log(Url.innerHTML)
      Url.select();
      document.execCommand("copy");
    }
  }

However, you should take a look to this link for a better cross-browsing solution. In this case you don't need the ref attribute.

This is the solution in the link adapted to your case:

methods: {
    copyUrl() {
        const el = document.createElement('textarea');  
        el.value = this.link_url;                                 
        el.setAttribute('readonly', '');                
        el.style.position = 'absolute';                     
        el.style.left = '-9999px';                      
        document.body.appendChild(el);                  
        const selected =  document.getSelection().rangeCount > 0  ? document.getSelection().getRangeAt(0) : false;                                    
        el.select();                                    
        document.execCommand('copy');                   
        document.body.removeChild(el);                  
        if (selected) {                                 
          document.getSelection().removeAllRanges();    
          document.getSelection().addRange(selected);   
        }
    }
}
Condemnation answered 6/11, 2019 at 16:42 Comment(5)
Thanks for the answer @fabruex. I have many links on a page, would $ref refer only to the link within the component or is the scope of $refs global, thus referring to all links then? Would I need a unique ref for each link component?Pleasure
If you have multiple ref="foo" within the same component $refs.foo will refer to the last one in the DOM. If you a have ref="foo" in an element with the v-for attribute $refs.foo will be an array. Check this: blog.logrocket.com/…Condemnation
So this is not a viable vuejs solution. However, I like the other proposed solution you posted!Pleasure
Yes, you can add the url to copy as method parameter and for every link something like this in the template: <a :href="urlstring">{{ link_name }}</a><button @click="copyUrl(urlstring)">Copy URL</button>Condemnation
document.execCommand is deprecated. Please do not use it: developer.mozilla.org/en-US/docs/Web/API/Document/execCommand . Use navigator.clipboard instead: developer.mozilla.org/en-US/docs/Web/API/ClipboardTremaine
L
45

You can use navigator object with clipboard in javascript.

Note: navigator.clipboard.writeText is asynchronous.

methods: {
  async copyURL(mytext) {
    try {
      await navigator.clipboard.writeText(mytext);
      alert('Copied');
    } catch($e) {
      alert('Cannot copy');
    }
  }
}
Liebowitz answered 10/9, 2021 at 15:22 Comment(1)
Just a heads up, this will not work on a non HTTPS connectionClop
C
16

If you need to use vuejs ref add it as attribute

<a :href="link_url" class="text-dark" target="_blank" rel="noopener noreferrer" ref="mylink">
    {{ link_name }}
</a>

and use it in your method in the following way:

  methods: {
    copyURL() {
      var Url = this.$refs.mylink;
      Url.innerHTML = window.location.href;
      console.log(Url.innerHTML)
      Url.select();
      document.execCommand("copy");
    }
  }

However, you should take a look to this link for a better cross-browsing solution. In this case you don't need the ref attribute.

This is the solution in the link adapted to your case:

methods: {
    copyUrl() {
        const el = document.createElement('textarea');  
        el.value = this.link_url;                                 
        el.setAttribute('readonly', '');                
        el.style.position = 'absolute';                     
        el.style.left = '-9999px';                      
        document.body.appendChild(el);                  
        const selected =  document.getSelection().rangeCount > 0  ? document.getSelection().getRangeAt(0) : false;                                    
        el.select();                                    
        document.execCommand('copy');                   
        document.body.removeChild(el);                  
        if (selected) {                                 
          document.getSelection().removeAllRanges();    
          document.getSelection().addRange(selected);   
        }
    }
}
Condemnation answered 6/11, 2019 at 16:42 Comment(5)
Thanks for the answer @fabruex. I have many links on a page, would $ref refer only to the link within the component or is the scope of $refs global, thus referring to all links then? Would I need a unique ref for each link component?Pleasure
If you have multiple ref="foo" within the same component $refs.foo will refer to the last one in the DOM. If you a have ref="foo" in an element with the v-for attribute $refs.foo will be an array. Check this: blog.logrocket.com/…Condemnation
So this is not a viable vuejs solution. However, I like the other proposed solution you posted!Pleasure
Yes, you can add the url to copy as method parameter and for every link something like this in the template: <a :href="urlstring">{{ link_name }}</a><button @click="copyUrl(urlstring)">Copy URL</button>Condemnation
document.execCommand is deprecated. Please do not use it: developer.mozilla.org/en-US/docs/Web/API/Document/execCommand . Use navigator.clipboard instead: developer.mozilla.org/en-US/docs/Web/API/ClipboardTremaine
A
6

Most modern web explorers (2021) let you use this: navigator.clipboard.writeText("yourText");

Just in case you can also do this:

  const clipboardData =
    event.clipboardData ||
    window.clipboardData ||
    event.originalEvent?.clipboardData ||
    navigator.clipboard;

  clipboardData.writeText(message);
Autotoxin answered 9/7, 2021 at 22:8 Comment(0)
C
4

does not work for me, try this -

<input type="hidden" id="testing-code" :value="testingCode">

copyTestingCode () {
      let testingCodeToCopy = document.querySelector('#testing-code')
      testingCodeToCopy.setAttribute('type', 'text') 
      testingCodeToCopy.select()

      try {
        var successful = document.execCommand('copy');
        var msg = successful ? 'successful' : 'unsuccessful';
        alert('Testing code was copied ' + msg);
      } catch (err) {
        alert('Oops, unable to copy');
      }

      /* unselect the range */
      testingCodeToCopy.setAttribute('type', 'hidden')
      window.getSelection().removeAllRanges()
    },

https://codepen.io/PJCHENder/pen/jamJpj?editors=1010, please

Crumble answered 7/2, 2021 at 13:4 Comment(0)
S
4

in vue3


<template>
<input ref="pixCodeInput" type="text">
<button @click="copyPixCodeClick()" type="button">copiar código</button>
</template>

<script setup>
import { ref } from 'vue';

const pixCodeInput = ref(null);

function copyPixCodeClick() {
    navigator.clipboard.writeText(pixCodeInput.value.value);
}
</script>

Seringapatam answered 16/9, 2022 at 14:19 Comment(0)
M
1

use this

<v-btn @click='copyToClipboard()' class='mx-2'>btn text</v-btn>

and

method:{
copyToClipboard() {
let val = window.location.href
navigator.clipboard.writeText(val)
.then(() => {
                    this.$snackbar.showMessage({
                        content:'coppied',
                        color: 'success',
                        timeout: '1000'
                    });
                })
                .catch(err => {
                    console.log(err);
                });
              
        },
 }
Mallorymallow answered 6/11, 2019 at 15:50 Comment(0)
C
1

<template>
  <button @click="copyMe('Copied')">Copy Your Code</button>
</template>

<script setup>
import { ref } from 'vue'
function copyMe(){
  navigator.clipboard.writeText("Copy Clipboard");
}
</script>
Convenance answered 20/12, 2022 at 17:39 Comment(0)
A
1

enter image description here

Observe the input component with REF

<q-input
  ref="keypixcopy"
  class="col-12 col-md-2 q-mt-sm"
  label="keypix"
  v-model="stt.payload_pix_cc"
/>

The button to activate the copy function

<q-btn
  class="q-pr-sm q-pl-sm"
  rounded
  outline
  label="Copy Paste"
  color="primary"
  @click="copy"
/>

To obtain the reference with Composition API, we need to declare a ref:

const keypixcopy = ref(null);

Now create a function to read the REF and copy the contents of the input

async function copy() {
  await keypixcopy.value.focus();
  await keypixcopy.value.select();
  document.execCommand("copy");
}
Americano answered 28/11, 2023 at 18:11 Comment(0)
F
-1

TRY THIS FUNCTION:

async copy(mytext) {
               var input = document.createElement('input');
               input.setAttribute('value', mytext);
               input.value = mytext;        
               document.body.appendChild(input);
               try {
                    input.select();    
                    input.click();     
                    input.focus();
                    var successful = document.execCommand('copy');
                    var msg = successful ? 'successful' : 'unsuccessful';
                    console.log('Testing code was copied ' + successful + ' ' + msg);
                    
               } catch (err) {
                    console.log('Oops, unable to copy');
               }
               document.body.removeChild(input);          
          }
Fugate answered 16/3, 2022 at 14:23 Comment(1)
Please don't post "try this" answers. If you tested the code, why should they have to try? Instead, explain why you offer this alternative for all existing answers.Barbaresi

© 2022 - 2024 — McMap. All rights reserved.