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?

anonym-dev
quelle
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.

Sangram Nandkhile
quelle
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

Dan Dohotaru
quelle
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')"

jockeisorby
quelle
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
2
Hier erfahren
bringen
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>
Nabel
quelle
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);
}
John
quelle
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
3

Sie können dies mit Angular-Modulen erreichen:

navigator.clipboard.writeText('your text').then().catch(e => console.error(e));
Anantharaman Krishnamoorthy
quelle
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);
}
Durgesh Pal
quelle
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>
Rahul Basu
quelle
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

Chandrahasan
quelle
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);
  }
Shreeketh K.
quelle