Angular 5-复制到剪贴板


123

我正在尝试实现一个图标,单击该图标会将变量保存到用户的剪贴板。我目前已经尝试了几个库,但没有一个库能够这样做。

如何在Angular 5中将变量正确复制到用户剪贴板?


您可以使用ngxyz-c2c,有多种方法可以执行此操作。
Ankit Singh,

如果您使用的是Angular Material,则9.0.0版(2020年2月6日发行)引入了超级易于使用的剪贴板包。请参阅Angular文档和@Nabel的答案
乔治·霍金斯

Answers:


232

解决方案1:复制任何文本

的HTML

<button (click)="copyMessage('This goes to Clipboard')" value="click to copy" >Copy this</button>

.ts文件

copyMessage(val: string){
    const selBox = document.createElement('textarea');
    selBox.style.position = 'fixed';
    selBox.style.left = '0';
    selBox.style.top = '0';
    selBox.style.opacity = '0';
    selBox.value = val;
    document.body.appendChild(selBox);
    selBox.focus();
    selBox.select();
    document.execCommand('copy');
    document.body.removeChild(selBox);
  }

解决方案2:从文本框复制

的HTML

 <input type="text" value="User input Text to copy" #userinput>
      <button (click)="copyInputMessage(userinput)" value="click to copy" >Copy from Textbox</button>

.ts文件

    /* To copy Text from Textbox */
  copyInputMessage(inputElement){
    inputElement.select();
    document.execCommand('copy');
    inputElement.setSelectionRange(0, 0);
  }

在这里演示


解决方案3:导入第三方指令ngx-clipboard

<button class="btn btn-default" type="button" ngxClipboard [cbContent]="Text to be copied">copy</button>

解决方案4:自定义指令

如果您更喜欢使用自定义指令,请查看Dan Dohotaru的答案,这是一个使用实施的优雅解决方案ClipboardEvent


1
好主意,但我复制了您的第二个解决方案,但我一直遇到Cannot read property 'select' of undefined角度6。这个角度6兼容吗?
slevin

1
@slevin我不认为它与角度版本有任何关系。您是否将`#userinput`添加到输入中?
Sangram Nandkhile '18

1
@SangramNandkhile我一次又一次地检查,但仍然是相同的错误。这是我的代码<input *ngIf="invitation_code" type="text" readonly value="{{invitation_code}}" #userinput > <button *ngIf="code_success" (click)="copyInputMessage(userinput)" value="click to copy" > Copy code </button>谢谢
slevin

你甚至可以删除positionlefttop,和opacity。并将其替换为selBox.style.height = '0';
Mendy

小问题,应使用const不要让它
Stephen DuMont '18

70

我知道这已经在这里获得了很高的投票,但是我宁愿使用自定义指令方法,并像@jockeisorby所建议的那样依赖ClipboardEvent,同时还要确保正确删除了侦听器(需要提供相同的功能)对于添加和删除事件侦听器)

stackblitz 演示

import { Directive, Input, Output, EventEmitter, HostListener } from "@angular/core";

@Directive({ selector: '[copy-clipboard]' })
export class CopyClipboardDirective {

  @Input("copy-clipboard")
  public payload: string;

  @Output("copied")
  public copied: EventEmitter<string> = new EventEmitter<string>();

  @HostListener("click", ["$event"])
  public onClick(event: MouseEvent): void {

    event.preventDefault();
    if (!this.payload)
      return;

    let listener = (e: ClipboardEvent) => {
      let clipboard = e.clipboardData || window["clipboardData"];
      clipboard.setData("text", this.payload.toString());
      e.preventDefault();

      this.copied.emit(this.payload);
    };

    document.addEventListener("copy", listener, false)
    document.execCommand("copy");
    document.removeEventListener("copy", listener, false);
  }
}

然后这样使用

<a role="button" [copy-clipboard]="'some stuff'" (copied)="notify($event)">
  <i class="fa fa-clipboard"></i>
  Copy
</a>

public notify(payload: string) {
   // Might want to notify the user that something has been pushed to the clipboard
   console.info(`'${payload}' has been copied to clipboard`);
}

注意:请注意,window["clipboardData"]因为IE无法理解,e.clipboardData


3
使此指令可重用的荣誉。好想法!
Rod

1
确实,从12.x版本开始,Safari再次出现了问题:)
Dan Dohotaru

2
最小的解决方法是创建一个范围并将该范围添加到选择中,有效的解决方案如下所示:stackblitz.com/edit/angular-labs-copy-clipboard-r1
Dan Dohotaru

在IE中未定义window [“ clipboardData”]吗?任何想法 ?
维克多·约兹维克

48

我认为这是复制文本时更加干净的解决方案:

copyToClipboard(item) {
    document.addEventListener('copy', (e: ClipboardEvent) => {
      e.clipboardData.setData('text/plain', (item));
      e.preventDefault();
      document.removeEventListener('copy', null);
    });
    document.execCommand('copy');
  }

然后只需在html中的click事件上调用copyToClipboard即可。(click)=“ copyToClipboard('texttocopy')”


2
由于未定义e.clipboardData,因此无法在IE上运行。
Dan Dohotaru

9
此外,removelistener也不起作用,因为需要将原始侦听器作为参数传递
Dan Dohotaru 18-10-23

2
在此处查找如何使remove事件侦听器正常工作:stackoverflow.com/a/51843984/3849445
user123959 '19

在Angular 6中工作正常!在Chrome中测试。谢谢。
moreirapontocom


14

jockeisorby答案的修改版本,修复了未正确删除事件处理程序的问题。

copyToClipboard(item): void {
    let listener = (e: ClipboardEvent) => {
        e.clipboardData.setData('text/plain', (item));
        e.preventDefault();
    };

    document.addEventListener('copy', listener);
    document.execCommand('copy');
    document.removeEventListener('copy', listener);
}

1
在Firefox中无法使用。错误-– document.execCommand(‘cut’/‘copy’) was denied because it was not called from inside a short running user-generated event handler
OPTIMUS


1

以下方法可用于复制邮件:

export function copyTextAreaToClipBoard(message: string) {
  const cleanText = message.replace(/<\/?[^>]+(>|$)/g, '');
  const x = document.createElement('TEXTAREA') as HTMLTextAreaElement;
  x.value = cleanText;
  document.body.appendChild(x);
  x.select();
  document.execCommand('copy');
  document.body.removeChild(x);
}

这确实是一个很好的解决方案。我为我的应用程序尝试了它,并成功了。谢谢。
9:04揭幕


1

使用角度cdk复制

模块

import {ClipboardModule} from '@angular/cdk/clipboard';

以编程方式复制字符串:MyComponent.ts,

class MyComponent {
  constructor(private clipboard: Clipboard) {}

  copyHeroName() {
    this.clipboard.copy('Alphonso');
  }
}

单击一个元素以通过HTML复制:

<button [cdkCopyToClipboard]="longText" [cdkCopyToClipboardAttempts]="2">Copy text</button>

参考:https : //material.angular.io/cdk/clipboard/overview


0

首先建议的解决方案有效,我们只需要更改

selBox.value = val;

selBox.innerText = val;

HTML:

<button (click)="copyMessage('This goes to Clipboard')" value="click to copy" >Copy this</button>

.ts文件:

copyMessage(val: string){
    const selBox = document.createElement('textarea');
    selBox.style.position = 'fixed';
    selBox.style.left = '0';
    selBox.style.top = '0';
    selBox.style.opacity = '0';
    selBox.innerText = val;
    document.body.appendChild(selBox);
    selBox.focus();
    selBox.select();
    document.execCommand('copy');
    document.body.removeChild(selBox);
  }
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.