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

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



Solution 1:[1]

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
Link 3

Solution 2:[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>

Solution 3:[3]

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.

Solution 4:[4]

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

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Agil Atakishiyev
Solution 2 Lior Madav
Solution 3
Solution 4 Roufa