Angular 5 - Copia negli appunti


124

Sto cercando di implementare un'icona che, se cliccata, salverà una variabile negli appunti dell'utente. Al momento ho provato diverse librerie e nessuna di esse è stata in grado di farlo.

Come faccio a copiare correttamente una variabile negli appunti dell'utente in Angular 5?


puoi usare ngxyz-c2c , ci sono molti modi per farlo.
Ankit Singh

Se stai usando Angular Material, la versione 9.0.0 (rilasciata il 6 febbraio 2020) ha introdotto il pacchetto appunti super facile da usare . Vedi la documentazione Angular e la risposta di @ Nabel .
George Hawkins,

Risposte:


236

Soluzione 1: copia qualsiasi testo

HTML

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

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

Soluzione 2: copia da una casella di testo

HTML

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

file .ts

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

Demo qui


Soluzione 3: importare una direttiva di terze parti ngx-clipboard

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

Soluzione 4: direttiva personalizzata

Se preferisci utilizzare una direttiva personalizzata, controlla la risposta di Dan Dohotaru che è un'elegante soluzione implementata utilizzando ClipboardEvent.


1
Ottima idea, ma ho copiato la tua seconda soluzione e continuo ad entrare Cannot read property 'select' of undefinedin angolare 6. È compatibile con angular6?
Slevin

1
@slevin Non penso che sia correlato alla versione angolare in alcun modo. Hai aggiunto "# userinput" al tuo input?
Sangram Nandkhile

1
@SangramNandkhile Ho controllato ancora e ancora, ma sempre lo stesso errore. Questo è il mio codice <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>Grazie
slevin

È anche possibile rimuovere il position, left, top, e opacity. e sostituirlo con unselBox.style.height = '0';
Mendy

problema minore, dovrebbe usare const not let
Stephen DuMont

70

So che questo è già stato votato molto bene qui ormai, ma preferirei un approccio di direttiva personalizzato e fare affidamento su ClipboardEvent come suggerito da @jockeisorby, assicurandomi anche che l'ascoltatore sia rimosso correttamente (deve essere fornita la stessa funzione sia per l'aggiunta che per la rimozione dei listener di eventi)

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

e poi usalo come tale

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

Nota: nota che window["clipboardData"]è necessario per IE poiché non comprendee.clipboardData


3
Complimenti per aver reso questa direttiva riutilizzabile. Grande idea!
Rod

1
infatti, a partire dalla versione 12.x qualcosa, Safari è di nuovo problematico :)
Dan Dohotaru

2
una soluzione alternativa minima sarebbe creare un intervallo e aggiungere tale intervallo alla selezione, una soluzione funzionante sarebbe simile a questo stackblitz.com/edit/angular-labs-copy-clipboard-r1
Dan Dohotaru

window ["clipboardData"] non è definita per me in IE? Qualche idea ?
Victor Jozwicki

non funziona sui dispositivi mobili, ho usato invece il plugin ngx-clipboard
il catalin

50

Penso che questa sia una soluzione molto più pulita quando si copia il testo:

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

E poi chiama semplicemente copyToClipboard sull'evento click in html. (Clic) = "CopyToClipboard ( 'texttocopy')"


2
non funziona su IE a causa del fatto che e.clipboardData non è definito.
Dan Dohotaru

9
inoltre il removelistener non funziona in quanto l'ascoltatore originale deve essere passato come argomento
Dan Dohotaru

2
Guardate qui per come ottenere il lavoro rimuovere listener di eventi: stackoverflow.com/a/51843984/3849445
user123959

Funziona bene in Angular 6! Testato in Chrome. Grazie.
moreirapontocom

16

A partire da Angular Material v9, ora ha un CDK degli appunti

Appunti | Materiale angolare

Può essere usato semplicemente come

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

Esso funziona magicamente. Non ho mai saputo che ci fosse una soluzione adeguata!
Abdullah Feroz

1
disponibile da Angular Material v9.
andreivictor

14

Versione modificata della risposta di jockeisorby che risolve il problema della rimozione corretta del gestore eventi.

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

3

Puoi ottenere ciò utilizzando i moduli angolari:

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

1

Il seguente metodo può essere utilizzato per copiare il messaggio: -

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

Questa è davvero una buona soluzione. L'ho provato per la mia applicazione e ha funzionato. Grazie.
jaihind il

1

Il modo migliore per farlo in Angular e mantenere il codice semplice è usare questo progetto.

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

Copia usando angular cdk,

Module.ts

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

Copiare una stringa a livello di codice: MyComponent.ts,

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

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

Fare clic su un elemento da copiare tramite HTML:

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

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


0

La prima soluzione suggerita funziona, dobbiamo solo cambiare

selBox.value = val;

Per

selBox.innerText = val;

vale a dire,

HTML:

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

file .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);
  }
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.