【问题标题】:Angular 5 - Copy to clipboardAngular 5 - 复制到剪贴板
【发布时间】:2018-08-12 15:38:20
【问题描述】:

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

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

【问题讨论】:

  • 你可以使用ngxyz-c2c,有多种方法。
  • 如果您使用的是 Angular Material,那么版本 9.0.0(2020 年 2 月 6 日发布)引入了超级易用的 clipboard package。请参阅 Angular 文档和 @Nabel 的 answer

标签: angular typescript angular5


【解决方案1】:

解决方案 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);
  }

Demo Here


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

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

解决方案 4: 自定义指令

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


解决方案 5: Angular 材质

Angular material 9 + 用户可以利用built-in clipboard 功能复制文本。还有一些可用的自定义设置,例如限制复制数据的尝试次数。

【讨论】:

  • 好主意,但我复制了您的第二个解决方案,并且在 Angular 6 中不断收到 Cannot read property 'select' of undefined。这是 angular6 兼容的吗?
  • @slevin 我认为它与角度版本没有任何关系。您是否在输入中添加了`#userinput`?
  • @SangramNandkhile 我一次又一次地检查,但仍然是同样的错误。这是我的代码&lt;input *ngIf="invitation_code" type="text" readonly value="{{invitation_code}}" #userinput &gt; &lt;button *ngIf="code_success" (click)="copyInputMessage(userinput)" value="click to copy" &gt; Copy code &lt;/button&gt; 谢谢
  • 您甚至可以删除positionlefttopopacity。并将其替换为selBox.style.height = '0';
  • 小问题,应该使用 const 不让
【解决方案2】:

我知道这已经在这里得到了高度评​​价,但我宁愿采用自定义指令方法,并按照@jockeisorby 的建议依赖 ClipboardEvent,同时还要确保正确删除了侦听器(需要相同的功能为添加和删除事件侦听器提供)

stackblitz demo

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

注意:注意 IE 需要 window["clipboardData"],因为它不理解 e.clipboardData

【讨论】:

  • 感谢您将此指令设为可重用指令。好主意!
  • 确实,从 12.x 版本开始,Safari 又出现了问题 :)
  • 一个最小的解决方法是创建一个范围并将该范围添加到选择中,一个有效的解决方案看起来像这样stackblitz.com/edit/angular-labs-copy-clipboard-r1
  • window["clipboardData"] 在 IE 中对我来说是未定义的?有什么想法吗?
  • 它在移动设备上不起作用,我使用了 ngx-clipboard 插件
【解决方案3】:

我认为在复制文本时这是一个更简洁的解决方案:

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

然后在 html 中的点击事件上调用 copyToClipboard(click)="copyToClipboard('texttocopy')".

【讨论】:

  • 由于 e.clipboardData 未定义,因此无法在 IE 上运行。
  • 此外,removelistener 也不起作用,因为原始侦听器需要作为参数传递
  • 查看如何让移除事件监听器工作:stackoverflow.com/a/51843984/3849445
  • 在 Angular 6 中运行良好!在 Chrome 中测试。谢谢。
【解决方案4】:

从 Angular Material v9 开始,它现在有一个剪贴板 CDK

Clipboard | Angular Material

可以这么简单地使用

<button [cdkCopyToClipboard]="This goes to Clipboard">Copy this</button>

【讨论】:

  • 它就像一个魅力。从来不知道有合适的解决方案!
  • Angular Material v9 提供。
  • 但是是否需要安装所有 Angular Material 才能实现这个简单的复制到剪贴板?
  • @muasif80 它是 cdk 的一部分,所以我相信你只需要安装它
  • 是的,只需安装 ng add @angular/cdk 并在您的 app.module.ts 添加 import { ClipboardModule } from '@angular/cdk/clipboard' 并将其添加到您的模块导入中:imports: [ ..., ClipboardModule ]
【解决方案5】:

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

【讨论】:

  • 在 Firefox 中不工作。错误 - document.execCommand(‘cut’/‘copy’) was denied because it was not called from inside a short running user-generated event handler
【解决方案6】:

使用 angular cdk 复制,

模块.ts

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

【讨论】:

  • 这会强制你使用 Angular Material
  • 这比其他的要好得多。我在其他副本示例中有错误,并且我已经导入了 cdk。耶!
【解决方案7】:

您可以使用 Angular 模块实现此目的:

navigator.clipboard.writeText('your text').then().catch(e => console.error(e));

【讨论】:

    【解决方案8】:

    使用navigator.clipboard.writeText将内容复制到剪贴板

    navigator.clipboard.writeText(content).then().catch(e => console.error(e));
    

    【讨论】:

      【解决方案9】:

      以下方法可用于复制消息:-

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

      【讨论】:

      • 这确实是一个很好的解决方案。我为我的应用程序尝试了它并且它有效。谢谢。
      【解决方案10】:

      在 Angular 中执行此操作并保持代码简单的最佳方法是使用此项目。

      https://www.npmjs.com/package/ngx-clipboard

          <fa-icon icon="copy" ngbTooltip="Copy to Clipboard" aria-hidden="true" 
          ngxClipboard [cbContent]="target value here" 
          (cbOnSuccess)="copied($event)"></fa-icon>
      

      【讨论】:

        【解决方案11】:
        // for copy the text
        import { Clipboard } from "@angular/cdk/clipboard"; // first import this in .ts
         constructor(
            public clipboard: Clipboard
          ) { }   
         <button class="btn btn-success btn-block"(click) = "onCopy('some text')" > Copy< /button>
        
         onCopy(value) {
             this.clipboard.copy(value);
            }
        
        
         // for paste the copied text on button click :here is code
            
            <button class="btn btn-success btn-block"(click) = "onpaste()" > Paste < /button>
            
            onpaste() {
              navigator['clipboard'].readText().then(clipText => {
                console.log(clipText);
              });
            }
        

        【讨论】:

        • 感谢您提供此代码 sn-p,它可能会提供一些有限的即时帮助。正确的解释将通过说明为什么这是解决问题的好方法,将大大提高其长期价值,并使其对有其他类似问题的未来读者更有用。请编辑您的答案以添加一些解释,包括您所做的假设
        【解决方案12】:

        对我来说,document.execCommand('copy') 是在发出 deprecated 警告,而我需要复制的数据在 &lt;div&gt; 中作为 textNode 而不是 @ 987654323@或&lt;textarea&gt;

        这就是我在 Angular 7 中的做法(灵感来自 @Anantharaman 和 @Codemaker 的回答):

        <div id="myDiv"> &lt &nbsp This is the text to copy. &nbsp &gt </div>
        <button (click)="copyToClipboard()" class="copy-btn"></button>
        
         copyToClipboard() {
            const content = (document.getElementById('myDiv') as HTMLElement).innerText;
            navigator['clipboard'].writeText(content).then().catch(e => console.error(e));
        
          }
        }
        

        绝对不是最好的方法,但它可以达到目的。

        【讨论】:

          【解决方案13】:

          第一个建议的解决方案有效,我们只需要更改

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

          【讨论】:

            【解决方案14】:

            使用纯 Angular 和 ViewChild 为自己找到了最简单的解决方案。

            import { Component, ViewChild } from '@angular/core';
            
            @Component({
              selector: 'cbtest',
              template: `
                <input type="text" #inp/>
                <input type="button" (click)="copy ()" value="copy now"/>`
            })
            
            export class CbTestComponent
            {
              @ViewChild ("inp") inp : any;
            
              copy ()
              {
                // this.inp.nativeElement.value = "blabla";  // you can set a value manually too
            
                this.inp.nativeElement.select ();   // select
                document.execCommand ("copy");      // copy
                this.inp.nativeElement.blur ();     // unselect
              }
            }
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2020-10-29
              • 2015-08-27
              • 2015-08-31
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多