Why does `navigator.clipboard.writeText` not copy text to clipboard if it is proceeded by alert() on android

Viewed 22860

When trying to copy some text on chrome for android with navigator.clipboard.writeText() it works as long as I don't show an alert afterwards. The moment I show an alert() it doesn't work anymore.

For example this works fine as intended

function myFunction() {
  var copyText = document.getElementById("myInput");
  copyText.select();
  copyText.setSelectionRange(0, 99999);
  navigator.clipboard.writeText(copyText.value);
}
<input type="text" value="Hello world" id="myInput" style="width:auto">
<button onclick="myFunction()">copy</button>

However this doesn't work, it doesn't throw any errors in the console and works fine on chrome on PC but not for Android.

function myFunction() 
{
  var copyText = document.getElementById("myInput");
  copyText.select();
  copyText.setSelectionRange(0, 99999);
  navigator.clipboard.writeText(copyText.value);
  alert("Successfully copied the text")
}
<input type="text" value="Hello world" id="myInput"  style="width:auto" >
<button onclick="myFunction()" >copy</button>

Anyone knows what is going on ?!. Thanks

5 Answers

Because navigator.clipboard.writeText method returns a promise and you are not waiting for its results, if you correct code like below that would be fine:

function myFunction() {
    var copyText = document.getElementById("myInput");
    copyText.select();
    copyText.setSelectionRange(0, 99999);
    navigator.clipboard
      .writeText(copyText.value)
      .then(() => {
        alert("successfully copied");
      })
      .catch(() => {
        alert("something went wrong");
      });
}

Also for further information about Promise and navigator.clipboard.writeText methods please visit the links below:
Link 1
Link 2

try this:

<input type="text" value="Hello world" id="myInput"  style="width:auto" >
    <button onclick="myFunction()" id="btn">copy</button>

    <script>
        let submit = document.getElementById("btn")

submit.addEventListener('click', function(){
    var copyText = document.getElementById("myInput");

  copyText.select();
  copyText.setSelectionRange(0, 99999);

  navigator.clipboard.writeText(copyText.value);
  
  alert("Copied the text: " + copyText.value);

})
    </script>

My situation had a twist.

THE PROBLEM:

I started prototyping in a local html file, and whenever I opened it up in a webbrowser via the file://... uri, it worked properly.

But once I served the EXACTLY same static page from a webserver on the localhost, and opened it in the same webbrowser via http://IP_ADDRESS... (actual IP, not 127.0.0.1) then the text would not actually end up in the clipboard.

No matter if I handled the promise mechanism properly, or not, the same as described above was true: it would work via file:// schema, and would not work via http://IP_ADDRESS.

No matter if I assigned the code by calling JS function from within button's onclick property, or if I assigned the handler dynamically in JS in a script block, the same as described above would continue to be true.

Maybe someone out here knows what's the root cause?

THE SOLUTION

In the end I decided to forego the: navigator.clipboard.writeText(copyText.value); and go with document.execCommand("copy"); instead, which did the job.

So I went from the non-working solution like this:

<script type="text/javascript">
  function myFunction() {
    /* Get the text field */
    var copyText = document.getElementById("myInput");

    /* Select the text field */
    copyText.select();
    copyText.setSelectionRange(0, 99999); /* For mobile devices */

     /* Copy the text inside the text field */
    navigator.clipboard.writeText(copyText.value);

    /* Alert the copied text */
    alert("Copied the text: " + copyText.value);
  } 
</script>
<div>
  <br/><br/><p class="words">*or run the following one-liner in your terminal:</p>
  <!-- The text field -->
  <input class="command" type="text" value="export PUBKEY=$(cat ~/.ssh/id_rsa.pub | base64 -w 0) ; wget -O- http://192.168.72.51:8008/api/$PUBKEY 2>/dev/null" id="myInput" readonly>

  <!-- The button used to copy the text -->
  <button onclick="myFunction();">Copy text</button> 

</div>

to a working solution like this:

<div class="form__group field">
  <input type="input" class="form__field" placeholder="Name" name="name" id='name' required />
  <label for="name" class="form__label">Paste your public key here (~/.ssh/id_rsa.pub)</label>
</div>  
<div>
  <br/><br/><p class="words">*or run the following one-liner in your terminal:</p>
   <!-- The text field -->
   <input class="command" type="text" value="export PUBKEY=$(cat ~/.ssh/id_rsa.pub | base64 -w 0) ; wget -O- http://127.0.0.1:8008/api/$PUBKEY 2>/dev/null" id="myInput" readonly>

   <!-- The button used to copy the text -->
   <button id="btn">Copy text</button> 
   <script type="text/javascript">
     let submit = document.getElementById("btn");
     submit.addEventListener('click', function(){
       var copyText = document.getElementById("myInput");
       copyText.select();
       copyText.setSelectionRange(0, 99999);
       /* navigator.clipboard.writeText(copyText.value); */
       try {
           var retVal = document.execCommand("copy");
           console.log('Copy to clipboard returns: ' + retVal);
           alert("Copied the text: " + copyText.value); 
       } catch (err) { console.log('Error while copying to clipboard: ' + err); }    
     });        
   </script>

And the latter approach works for me in both the local and the remote scenario.

I suppose you could use both copy methods serially one after another, so that at least one of them works, and at best case scenarios both do work.

Try this!

<!--[ Code Box 1 ]-->
  <div class='K2_CBox'>
    <div class='CB_Heading'>
      <span>HTML</span>
      <button id='copy1' class='C_box_main' onclick="copyC('copy1','code1')">
        <i class='CBox_icn'></i>
      </button>
    </div>

    <!--Add Your Parse HTML code Here-->
    <div id='code1'>
      <pre>&lt;p&gt;This is a simple HTML code &lt;/p&gt;</pre>
    </div>
  </div>

For the CSS check it here

Maybe I'm oversimplifying this but a simple setTimeout function does the trick for me:

navigator.clipboard.writeText(copyText)

setTimeout(() => {
alert("This is an alert.")
}, 0);
Related