Angular 5 - скопировать в буфер обмена

127

Я пытаюсь реализовать значок, который при нажатии сохранит переменную в буфер обмена пользователя. В настоящее время я пробовал несколько библиотек, и ни одна из них не смогла этого сделать.

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

анонимный разработчик
источник
вы можете использовать ngxyz-c2c , есть несколько способов сделать это.
Анкит Сингх,
Если вы используете Angular Material, то версия 9.0.0 (выпущенная 6 февраля 2020 г.) представила очень простой в использовании пакет буфера обмена . См. Документацию Angular и ответ @ Nabel .
Джордж Хокинс,

Ответы:

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. Специальная директива

Если вы предпочитаете использовать настраиваемую директиву, проверьте ответ Дэна Дохотару, который представляет собой элегантное решение, реализованное с использованием ClipboardEvent.

Санграм Нандкхиле
источник
1
Отличная идея, но я скопировал ваше второе решение и продолжаю использовать Cannot read property 'select' of undefinedangular 6. Совместимо ли это с angular6?
slevin 07
1
@slevin Я не думаю, что это как-то связано с угловой версией. Вы добавляли в свой ввод `# userinput`?
Санграм Нандкхиле 09
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 09
Вы даже можете удалить position, left, top, и opacity. и замените его наselBox.style.height = '0';
Менди
незначительная проблема, следует использовать const, не позволяйте
Стивен Дюмон
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 снова проблематичен :)
Дэн Дохотару
2
минимальный обходной путь - создать диапазон и добавить этот диапазон к выделенному
Дэн Дохотару
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')"

Jockeisorby
источник
2
не работает в IE из-за того, что e.clipboardData не определен.
Дэн Дохотару
9
кроме того, программа восстановления не работает, так как исходный слушатель должен быть передан в качестве аргумента
Дэн Дохотару
2
Посмотрите здесь, как заставить работать прослушиватель событий remove: stackoverflow.com/a/51843984/3849445
user123959
Прекрасно работает в Angular 6! Проверено в Chrome. Спасибо.
moreirapontocom
17

Что касается Angular Material 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
3

Вы можете добиться этого с помощью модулей Angular:

navigator.clipboard.writeText('your text').then().catch(e => console.error(e));
Анантараман Кришнамурти
источник
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

Скопируйте с помощью angular 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

Chandrahasan
источник
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);
  }
Shreeketh K
источник