Кутова 5 - Скопіюйте у буфер обміну


124

Я намагаюся реалізувати іконку, яка при натисканні збереже змінну в буфер обміну користувача. Наразі я спробував кілька бібліотек, і жодна з них не змогла це зробити.

Як правильно скопіювати змінну в буфер обміну користувача у Angular 5?


ви можете використовувати ngxyz-c2c , існує кілька способів зробити це.
Анкіт Сінгх

Якщо ви використовуєте Angular Material, тоді у версії 9.0.0 (випущена 6 лютого 2020 року) представлений пакет простого у користуванні буфера обміну . Див Кутове документацію і @ Набель в відповідь .
Джордж Хокінс

Відповіді:


235

Рішення 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: Копіювання з 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 файл

    /* 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: Спеціальна директива

Якщо ви віддаєте перевагу використовувати призначену для користувача директиву, Check Dan Дохотару в відповідь , який є елегантним рішенням , реалізованим з використанням ClipboardEvent.


1
Чудова ідея, але я скопіював ваше друге рішення, і я продовжую отримувати Cannot read property 'select' of undefinedкут 6. Чи це кутовий 6 сумісний?
слевін

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';
Менді

другорядний випуск, слід використовувати const not let
Stephen DuMont

70

Я знаю, що це вже зараз проголосували тут, але я скоріше скористаюся спеціальним підходом до директив і покладусь на ClipboardEvent, як запропонував @jockeisorby, а також переконавшись, що слухач правильно видалений (цю функцію потрібно надати для слухачів додавання та видалення подій)

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

Примітка: зауважте, що window["clipboardData"]потрібно для IE, оскільки він не розумієe.clipboardData


3
Кудо для того, щоб зробити цю директиву багаторазовою. Чудова ідея!
Прут

1
Дійсно, починаючи з версії 12.x щось, Safari знову проблематично :)
Dan

2
мінімальним вирішенням буде створення діапазону та додавання цього діапазону до вибору. Робоче рішення виглядатиме таким чином stackblitz.com/edit/angular-labs-copy-clipboard-r1
Dan

вікно ["clipboardData"] не визначене для мене в IE? Будь-яка ідея?
Віктор Йозвіцкі

він не працює на мобільних пристроях, а я використовував плагін ngx-clipboard
the-catalin

49

Я думаю, що це набагато більш чітке рішення при копіюванні тексту:

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

А потім просто зателефонуйте copyToClipboard на подію клацання в html. (click) = "copyToClipboard ('texttocopy')"


2
не працює на IE через те, що e.clipboardData не визначено.
Дан Дохотару

9
до того ж Removelistener не працює ні тому, що оригінального слухача потрібно передавати як аргумент
Dan Dohotaru

2
Подивіться тут , як отримати видалити слухач подій роботи: stackoverflow.com/a/51843984/3849445
user123959

Добре працює в кутовій 6! Тестували в Chrome. Дякую.
moreirapontocom

16

Що стосується кутового матеріалу v9, він тепер має буфер обміну CDK

Буфер обміну | Кутовий матеріал

Його можна використовувати так само просто

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

Це працює як шарм. Ніколи не знав, що правильного рішення не було!
Абдулла Фероз

1
доступний від Angular Material v9.
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

Найкращий спосіб зробити це в 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>

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);
  }
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.