Search code examples
javascriptvue.jsvuejs2vue-componentnuxt.js

Copy url to clipboard via button click in a vuejs component


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>

Solution

  • 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);   
            }
        }
    }