kayasa
kayasa

Reputation: 2085

Angular 4 - Copy text to clipboard

I have a clickable icon on the page. On click on this icon, I would like to construct some text and copy that in the clipboard

<td><img src='./assets/Copy.gif' (click)="copyToClipboard()"  /></td> 

and in the Component

  copyToClipboard() {
     this.textToCopy = this.text1 + this.text2 + this.text3;  
     this.toastr.info('Copied to Clipboard');
  }

I have looked at https://www.npmjs.com/package/ngx-clipboard. However, this package requires to refer to an input element and copy the text from that input element. In my use case, the text needs to be dynamically created and then added to clipboard.

Can I use ngx-clipboard to copy to clipboard or is there be another package that would enable me to achieve this?

Upvotes: 19

Views: 36579

Answers (6)

Gangadhar Jannu
Gangadhar Jannu

Reputation: 4414

User interaction is mandatory for executing document.execCommand, which is used for copying text to the clipboard.

See my other answer.

If you don't want to use any third party library, you could use below snippet for copying text to the clipboard.

function copyTextToClipboard(text) {
  var txtArea = document.createElement("textarea");
  txtArea.id = 'txt';
  txtArea.style.position = 'fixed';
  txtArea.style.top = '0';
  txtArea.style.left = '0';
  txtArea.style.opacity = '0';
  txtArea.value = text;
  document.body.appendChild(txtArea);
  txtArea.select();

  try {
    var successful = document.execCommand('copy');
    var msg = successful ? 'successful' : 'unsuccessful';
    console.log('Copying text command was ' + msg);
    if (successful) {
      return true;
    }
  } catch (err) {
    console.log('Oops, unable to copy');
  } finally {
    document.body.removeChild(txtArea);
  }
  return false;
}

Change copyToClipboard function as below to call the copyTextToClipboard function

copyToClipboard() {
    this.textToCopy = this.text1 + this.text2 + this.text3;
    var result = this.copyTextToClipboard(this.textToCopy);
    if (result) {
        this.toastr.info('Copied to Clipboard');
    }
}

Upvotes: 20

dilantha111
dilantha111

Reputation: 1498

ngx-clipboard now doesn't require you to use input element. Now it's more straight forward and provide several ways of doing this. One way to do is simply use ClipboardService. From three, documentation

import { ClipboardService } from 'ngx-clipboard'

constructor(private _clipboardService: ClipboardService){
...
}
copy(text: string){
  this._clipboardService.copyFromContent(text)
}

But in my case this didn't work. And I got some warnings at the compile time in angular that peer dependencies are not met. Since I was using Angular 4 these warning I expected. But there's a simple way to do this with @ViewChild if the above solution doesn't work for you.

in your html :

<textarea name="copyText" #copyText id="" style="opacity: 0;height: 0;"></textarea>

And in Component :

@ViewChild('copyText', { read: ElementRef }) copyText: ElementRef;

copyText() {
    const element = this.copyText.nativeElement;
    element.value = 'some text';
    element.focus();
    element.select();
    document.execCommand('copy');
}

This is just simple vanilla javascript approach with Angular's @ViewChild

Upvotes: 3

Philo
Philo

Reputation: 176

The problem (later highlighted by the OP) of the approved answer, using NgxClipboard, is that the content could not be set dynamically.

Using a (click) event listener doesn't work, because it is triggered after ngxClipboard execution.

So, simply define [cbContent] with an @Input getter, and forget about the (click) event:

In the template:

<button ngxClipboard [cbContent]="foo">Click me</button>

In the component:

@Input()
get foo() {
    // Dynamic generation of the text to put in the clipboard:
    return this.text1 + this.text2 + this.text3
}

Upvotes: 0

velval
velval

Reputation: 3312

Here another quick and dirty option without the need of third-party libraries or modules. Taken from here

In your template

<a class="accent" (click)="copyLink(textToCopy)">{{textToCopy}}</a>

And in your component

copyLink(text:string) {
        const event = (e: ClipboardEvent) => {
            e.clipboardData.setData('text/plain', text);
            e.preventDefault();
            // ...('copy', e), as event is outside scope
            document.removeEventListener('copy', e);
        }
        document.addEventListener('copy', event);
        document.execCommand('copy');
    }

Upvotes: 9

FAISAL
FAISAL

Reputation: 34673

You need to use ngxClipboard directive with your image. This is how you need to use it to solve your issue:

<td>
    <img src='./assets/Copy.gif' (click)="copyToClipboard()" ngxClipboard [cbContent]="textToCopy" />
</td> 

Remember to add ClipboardModule in your app module. Example code below:

import { ClipboardModule } from 'ngx-clipboard';

@NgModule({
  imports: [
    // Other Imports
    ClipboardModule
  ],
  // Other code
})
export class AppModule { }

Upvotes: 17

Zahidul Islam Ruhel
Zahidul Islam Ruhel

Reputation: 1134

This is the easiest way to copy to clipboard.

In your template

<button (click)="copyToClipboard(sharableLink)">Copy link</button>
<input type="text" value="This is the value to copy" #sharableLink>

In component

copyToClipboard(element) {
    element.select();
    document.execCommand('copy');
    this.toaster('success', 'Success!', 'Link copied to clipboard.');
  }

Upvotes: 15

Related Questions