Angular 4 - 复制文本到剪贴板

19

我在页面上有一个可点击的图标。当点击此图标时,我希望构建一些文本并将其复制到剪贴板中

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

并且在组件中

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

我已经查看了https://www.npmjs.com/package/ngx-clipboard。然而,该包要求引用一个输入元素并复制该输入元素中的文本。在我的使用场景中,文本需要动态创建,然后添加到剪贴板。

我能否使用ngx-clipboard将文本复制到剪贴板,或者有其他软件包可以实现这一点?


浏览器支持? - Buddybear
Internet Explorer 11 - kayasa
6个回答

20

执行 document.execCommand 来复制文本到剪贴板需要用户交互。

请查看我的其他答案

如果不想使用任何第三方库,您可以使用下面的代码片段来复制文本到剪贴板。

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

copyToClipboard 函数更改为以下内容以调用 copyTextToClipboard 函数

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

我没有需要获取文本的文本区域。文本将来自于服务。一旦用户点击'复制'图标,就会调用一个服务,该服务将生成文本,然后将此文本复制到剪贴板中。 - kayasa
它将即时创建文本区域。您不需要拥有它。您需要做的就是根据答案中提到的更改 copyToClipboard 函数。 - Buddybear
@kayasa 在异步调用中无法将文本复制到剪贴板。要么您应该有可用的文本,要么调用应该是同步的。 - Vip
2
这个解决方案很好用。他正在创建一个DOM并使用select,Angular的问题在于编译器在TypeScript中找不到select方法,但在这种情况下,他创建了一个文本区域元素并将文本附加到复制中,这样就能使用select()方法了。谢谢! - Rafael Paredes
@GangadharJannu 实际上,在成功的复制操作中它并没有被删除。我已经更新了你的答案。 - Halil
显示剩余2条评论

16

您需要在图像上使用 ngxClipboard 指令。以下是解决问题的使用方法:

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

记得在你的应用程序模块中添加ClipboardModule。以下是示例代码:

记得在您的应用模块中添加ClipboardModule。下面是示例代码:
import { ClipboardModule } from 'ngx-clipboard';

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

谢谢。这个错误信息告诉我cbContent不是img的已知属性 - "无法绑定到'cbContent',因为它不是'img'的已知属性。" - kayasa
你必须在AppModule的导入中包含FormsModuleClipboardModule。然后它就会起作用。 - FAISAL
是的,它确实处理了错误。但是有一个问题。它没有考虑copyToClipboard()函数中更新的文本,而是采用了在调用该函数之前的textToCopy的值。textToCopy: string = 'Hello'; copyToClipboard() { this.textToCopy = this.textToCopy + '! How are you!'; } 将被复制的文本是'Hello'而不是'Hello! How are you!'。有没有办法复制更新后的文本? - kayasa
ngxClipboard工作得非常好 - 最新版本暴露了一个(cbOnSuccess)事件,您可以链接到它而不是使用click事件。这应该解决上述使用click捕获的特殊问题。 - Scott Byers
始终出错:目标应该是输入框或文本域 在ClipboardService.push../node_modules/ngx-clipboard/dist/src/clipboard.service.js.ClipboardService.isTargetValid处 - Anton Pegov

15

这是最简单的复制到剪贴板的方法。

在您的模板中

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

组件中

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

3
如果您不希望文本在单击后保持选中状态,只需在execCommand之后添加element.setSelectionRange(0, 0)。 - jbojcic
是的,谢谢... @jbojcic - Zahidul Islam Ruhel
如何使用此功能复制多个HTML元素。https://stackoverflow.com/questions/53374846/copy-to-clipboard-from-two-html-elements - Nancy
我认为这应该是被接受的答案,因为它比添加一些第三方模块来完成这个简单的任务更加优雅 :) - Khobar

9
这里提供一种快速而简单的选项,不需要使用第三方库或模块。在您的模板中,可以按照以下链接的方式实现。 来源
<a class="accent" (click)="copyLink(textToCopy)">{{textToCopy}}</a>

在你的组件中,
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');
    }

3

现在,ngx-clipboard不再需要您使用input元素。现在更加直观,并提供了几种方法来完成此操作。其中一种方法是简单地使用ClipboardService。详情请参阅文档。

import { ClipboardService } from 'ngx-clipboard'

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

但在我的情况下,这并没有奏效。在angular的编译时,我收到了一些警告,表示未满足对等依赖项。由于我使用的是Angular 4,所以我预计会出现这些警告。

但是,如果上述解决方案不适用于您,可以使用@ViewChild来简单解决此问题。

在您的html中:

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

在组件中:
@ViewChild('copyText', { read: ElementRef }) copyText: ElementRef;

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

这只是一个使用Angular的@ViewChild的简单纯JavaScript方法。


0

被批准的答案使用NgxClipboard存在问题(稍后由OP突出显示),即内容无法动态设置。

使用(click)事件监听器不起作用,因为它在ngxClipboard执行之后触发。

因此,只需使用@Input getter定义[cbContent],并忘记(click)事件:

在模板中:

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

在组件中:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接