Angular 5 - คัดลอกไปยังคลิปบอร์ด


127

ฉันกำลังพยายามใช้ไอคอนที่เมื่อคลิกจะบันทึกตัวแปรลงในคลิปบอร์ดของผู้ใช้ ขณะนี้ฉันได้ลองใช้ไลบรารีหลายแห่งและไม่มีไลบรารีใดที่สามารถทำได้

ฉันจะคัดลอกตัวแปรไปยังคลิปบอร์ดของผู้ใช้ใน Angular 5 อย่างถูกต้องได้อย่างไร


คุณสามารถใช้ngxyz-c2cได้หลายวิธีในการทำ
Ankit Singh

หากคุณใช้ Angular Material เวอร์ชัน 9.0.0 (เผยแพร่เมื่อวันที่ 6 กุมภาพันธ์ 2020) จะแนะนำแพ็คเกจคลิปบอร์ดที่ใช้งานง่ายสุดๆ ดูเอกสารและเชิงมุม @ Nabel ของคำตอบ
George Hawkins

คำตอบ:


237

โซลูชันที่ 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
ความคิดที่ดี แต่ฉันคัดลอกโซลูชันที่ 2 ของคุณและฉันได้รับCannot read property 'select' of undefinedในเชิงมุม 6 นี้เข้ากันได้กับ angular6 หรือไม่?
slevin

1
@slevin ฉันไม่คิดว่ามันเกี่ยวข้องกับเวอร์ชั่นเชิงมุม แต่อย่างใด คุณเพิ่ม "# userinput" ลงในอินพุตของคุณหรือไม่
Sangram Nandkhile

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

คุณยังสามารถลบposition, left, และtop opacityและแทนที่ด้วยselBox.style.height = '0';
Mendy

ปัญหาเล็กน้อยควรใช้ const not let
Stephen DuMont

70

ฉันรู้ว่าตอนนี้ได้รับการโหวตอย่างสูงแล้วในตอนนี้ แต่ฉันควรเลือกแนวทางที่กำหนดเองและพึ่งพา ClipboardEvent ตามที่ @jockeisorby แนะนำในขณะเดียวกันก็ตรวจสอบให้แน่ใจว่าผู้ฟังถูกลบออกอย่างถูกต้อง (ต้องมีฟังก์ชันเดียวกัน สำหรับผู้ฟังเหตุการณ์ทั้งเพิ่มและลบ)

การสาธิต 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

window ["clipboardData"] ไม่ได้กำหนดไว้สำหรับฉันใน IE? ความคิดใด ๆ ?
Victor Jozwicki

มันไม่ทำงานบนมือถือฉันใช้ปลั๊กอิน ngx-clipboard แทน
the-catalin

50

ฉันคิดว่านี่เป็นวิธีแก้ปัญหาที่สะอาดกว่ามากเมื่อคัดลอกข้อความ:

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

จากนั้นเรียก copyToClipboard เมื่อคลิกเหตุการณ์ใน html (คลิก) = "copyToClipboard ( 'texttocopy')"


2
ไม่ทำงานบน IE เนื่องจากไม่ได้กำหนด e.clipboardData
Dan Dohotaru

9
ยิ่งไปกว่านั้นตัวลบรายการไม่ทำงานอย่างใดอย่างหนึ่งเนื่องจากผู้ฟังต้นฉบับจะต้องถูกส่งผ่านเป็นอาร์กิวเมนต์
Dan Dohotaru

2
ดูวิธีการทำให้ตัวฟังเหตุการณ์ลบทำงานได้ที่นี่: stackoverflow.com/a/51843984/3849445
user123959

ทำงานได้ดีใน Angular 6! ทดสอบใน Chrome ขอบคุณ.
moreirapontocom

17

สำหรับ Angular Material v9 ตอนนี้มีคลิปบอร์ด CDK แล้ว

คลิปบอร์ด | วัสดุเชิงมุม

สามารถใช้งานได้ง่ายๆ

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

มันใช้งานได้เหมือนมีเสน่ห์ ไม่เคยรู้วิธีแก้ปัญหาที่เหมาะสมมาก่อน!
Abdullah Feroz

1
หาได้จาก Angular Material v9.0
andreivictor

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

นี่เป็นทางออกที่ดี ฉันลองใช้กับแอปพลิเคชันของฉันและมันได้ผล ขอบคุณ
jaihind


1

คัดลอกโดยใช้ cdk เชิงมุม

Module.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


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);
  }
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.