Winkel 5 - In Zwischenablage kopieren


123

Ich versuche, ein Symbol zu implementieren, das beim Klicken eine Variable in der Zwischenablage des Benutzers speichert. Ich habe derzeit mehrere Bibliotheken ausprobiert und keine von ihnen war dazu in der Lage.

Wie kopiere ich eine Variable in Angular 5 ordnungsgemäß in die Zwischenablage des Benutzers?


Sie können ngxyz-c2c verwenden , es gibt mehrere Möglichkeiten, dies zu tun.
Ankit Singh

Wenn Sie Angular Material verwenden, hat Version 9.0.0 (veröffentlicht am 6. Februar 2020) das super einfach zu verwendende Zwischenablage-Paket eingeführt . Siehe die Angular-Dokumentation und die Antwort von @ Nabel .
George Hawkins

Antworten:


232

Lösung 1: Kopieren Sie einen beliebigen Text

HTML

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

.ts Datei

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

Lösung 2: Kopieren aus einer TextBox

HTML

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

.ts Datei

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

Demo hier


Lösung 3: Importieren Sie eine Direktive ngx-clipboard eines Drittanbieters

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

Lösung 4: Benutzerdefinierte Richtlinie

Wenn Sie eine benutzerdefinierte Direktive bevorzugen, überprüfen Sie die Antwort von Dan Dohotaru, bei der es sich um eine elegante Lösung handelt, die mit implementiert wird ClipboardEvent.


1
Tolle Idee, aber ich habe Ihre 2. Lösung kopiert und komme immer wieder Cannot read property 'select' of undefinedin Winkel 6. Ist das eckig6-kompatibel?
Slevin

1
@slevin Ich glaube nicht, dass es in irgendeiner Weise mit der Winkelversion zusammenhängt. Haben Sie Ihrer Eingabe "# userinput" hinzugefügt?
Sangram Nandkhile

1
@ SangramNandkhile Ich habe immer wieder nachgesehen, aber immer noch den gleichen Fehler. Dies ist mein Code <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>Danke
Slevin

Sie können sogar entfernen Sie die position, left, top, und opacity. und ersetzen Sie es durch einselBox.style.height = '0';
Mendy

kleines Problem, sollte const nicht lassen
Stephen DuMont

70

Ich weiß, dass dies hier bereits hoch bewertet wurde, aber ich würde mich lieber für einen benutzerdefinierten Direktivenansatz entscheiden und mich auf das ClipboardEvent verlassen, wie von @jockeisorby vorgeschlagen, und gleichzeitig sicherstellen, dass der Listener korrekt entfernt wird (dieselbe Funktion muss bereitgestellt werden) für die Listener zum Hinzufügen und Entfernen von Ereignissen)

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

und dann als solches verwenden

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

Hinweis: Beachten Sie, dass das window["clipboardData"]für IE benötigt wird, da es nicht verstehte.clipboardData


3
Ein großes Lob dafür, dass dies eine wiederverwendbare Richtlinie ist. Großartige Idee!
Rod

1
In der Tat ist Safari ab Version 12.x wieder problematisch :)
Dan Dohotaru

2
Eine minimale Problemumgehung wäre, einen Bereich zu erstellen und diesen Bereich zur Auswahl hinzuzufügen. Eine funktionierende Lösung würde so aussehen: stackblitz.com/edit/angular-labs-copy-clipboard-r1
Dan Dohotaru

window ["clipboardData"] ist für mich im IE undefiniert? Irgendeine Idee ?
Victor Jozwicki

48

Ich denke, dies ist eine viel sauberere Lösung beim Kopieren von Text:

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

Und dann rufen Sie einfach copyToClipboard beim Klickereignis in HTML auf. (click) = "copyToClipboard ('texttocopy')"


2
funktioniert nicht im IE, da e.clipboardData nicht definiert ist.
Dan Dohotaru

9
Darüber hinaus funktioniert der Removelistener auch nicht, da der ursprüngliche Listener als Argument übergeben werden muss
Dan Dohotaru


Funktioniert gut in Angular 6! In Chrome getestet. Danke dir.
moreirapontocom

16

Ab Angular Material v9 verfügt es jetzt über ein CDK für die Zwischenablage

Zwischenablage | Winkelmaterial

Es kann so einfach wie verwendet werden

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

Es wirkt wie ein Zauber. Ich wusste nie, dass es eine richtige Lösung gibt!
Abdullah Feroz

1
erhältlich bei Angular Material v9.
andreivictor

14

Geänderte Version von Jockeisorbys Antwort, die behebt, dass der Ereignishandler nicht ordnungsgemäß entfernt wird.

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
Funktioniert nicht in Firefox. Fehler -document.execCommand(‘cut’/‘copy’) was denied because it was not called from inside a short running user-generated event handler
OPTIMUS


1

Die folgende Methode kann zum Kopieren der Nachricht verwendet werden: -

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

Dies ist in der Tat eine gute Lösung. Ich habe es für meine Anwendung versucht und es hat funktioniert. Vielen Dank.
Jaihind

1

Der beste Weg, dies in Angular zu tun und den Code einfach zu halten, ist die Verwendung dieses Projekts.

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>

1

Kopieren mit eckigen cdk,

Module.ts

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

Kopieren Sie programmgesteuert eine Zeichenfolge: MyComponent.ts,

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

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

Klicken Sie auf ein Element, um es über HTML zu kopieren:

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

Referenz: https://material.angular.io/cdk/clipboard/overview


0

Der erste Lösungsvorschlag funktioniert, wir müssen ihn nur ändern

selBox.value = val;

Zu

selBox.innerText = val;

dh

HTML:

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

.ts Datei:

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);
  }
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.