How do I copy to clipboard in Angular 2 Typescript?

前端 未结 10 1044
-上瘾入骨i
-上瘾入骨i 2020-12-03 06:45

Is there a way to copy text in clipboard (multi-browser) in Angular2 Typescript framework?

I find only sources of using Javascript, e.g.

document.exe         


        
相关标签:
10条回答
  • 2020-12-03 07:38

    Here is a simple code in case your text is not inside an input or textarea, but a div, or any other HTMLElement and you don't want to use any external libraries:

    window.getSelection().selectAllChildren(document.getElementById('yourID'));
    document.execCommand("copy");
    

    I was unable to use the select() command because it wasn't recognized by Angular. Hope this helps someone!

    0 讨论(0)
  • 2020-12-03 07:38

    Here is a way to achieve this without any external dependency or creating fake elements, only by using Clipboard API:

    import { DOCUMENT } from '@angular/common';
    import { Directive, EventEmitter, HostListener, Inject, Input, Output } from '@angular/core';
    
    @Directive({
      selector: '[myClipboard]'
    })
    export class ClipboardDirective {
    
      @Input() myClipboard: string;
      @Output() myClipboardSuccess = new EventEmitter<ClipboardEvent>();
    
      constructor(@Inject(DOCUMENT) private document: Document) {}
    
      @HostListener('click')
      onClick() {
        this.document.addEventListener('copy', this.handler);
        this.document.execCommand('copy');
      }
    
      private handler = (e: ClipboardEvent) => {
        e.clipboardData.setData('text/plain', this.myClipboard);
        e.preventDefault();
        this.myClipboardSuccess.emit(e);
        this.document.removeEventListener('copy', this.handler);
      }
    
    }
    

    Can I use Clipboard API?

    0 讨论(0)
  • 2020-12-03 07:40

    Kudos to @ThierryTemplier,

    Base on his answer, I put together a directive and sharing on github & npm.

    Here is the project on github

    UPDATE: 4/30/2017

    This library doesn't depends on clipboard.js anymore.

    Just Angular!

    Quick example (component code):

    import { ClipboardService } from 'ngx-clipboard'
    
    ...
    
    constructor(private _clipboardService: ClipboardService){
    ...
    }
    
    // not sure, but this should the result of user interaction (e.g. (click) )
    copyToClipboard(){
      const text = computeText();
      this._clipboardService.copyFromContent(text)
    }
    
    0 讨论(0)
  • 2020-12-03 07:43

    Ben Nadel had a great example that worked for any html element type and doesn't rely on anything to be installed. See Ben's blog post Or see the Git gist

    See his blog for more about it and the logging he does, here's the relevant and slightly modified so it fits here better:

    Make a directive: clipboard.directive.ts

    // Import the core angular services.
    import { Directive } from "@angular/core";
    import { EventEmitter } from "@angular/core";
    
    // Import the application components and services.
    import { ClipboardService } from "./clipboard.service";
    
    // This directive acts as a simple glue layer between the given [clipboard] property
    // and the underlying ClipboardService. Upon the (click) event, the [clipboard] value
    // will be copied to the ClipboardService and a (clipboardCopy) event will be emitted.
    @Directive({
    selector: "[clipboard]",
    inputs: [ "value: clipboard" ],
    outputs: [
        "copyEvent: clipboardCopy",
        "errorEvent: clipboardError"
    ],
    host: {
        "(click)": "copyToClipboard()"
    }
    })
    export class ClipboardDirective {
    
    public copyEvent: EventEmitter<string>;
    public errorEvent: EventEmitter<Error>;
    public value: string;
    
    private clipboardService: ClipboardService;
    
    
    // I initialize the clipboard directive.
    constructor( clipboardService: ClipboardService ) {
    
        this.clipboardService = clipboardService;
        this.copyEvent = new EventEmitter();
        this.errorEvent = new EventEmitter();
        this.value = "";
    }
    
    // ---
    // PUBLIC METODS.
    // ---
    
    // I copy the value-input to the Clipboard. Emits success or error event.
    public copyToClipboard() : void {
        this.clipboardService
            .copy( this.value )
            .then(
                ( value: string ) : void => {
    
                    this.copyEvent.emit( value );
    
                }
            )
            .catch(
                ( error: Error ) : void => {
    
                    this.errorEvent.emit( error );
                }
            )
        ;
    }
    }
    

    And a service clipboard.service.ts

    // Import the core angular services.
    import { DOCUMENT } from "@angular/platform-browser";
    import { Inject } from "@angular/core";
    import { Injectable } from "@angular/core";
    @Injectable()
    export class ClipboardService {
    
    private dom: Document;
    // I initialize the Clipboard service.
    // --
    // CAUTION: This service is tightly couped to the browser DOM (Document Object Model).
    // But, by injecting the "document" reference rather than trying to reference it
    // globally, we can at least pretend that we are trying to lower the tight coupling.
    constructor( @Inject( DOCUMENT ) dom: Document ) {
        this.dom = dom;
    }
    
    // ---
    // PUBLIC METHODS.
    // ---
    // I copy the given value to the user's system clipboard. Returns a promise that
    // resolves to the given value on success or rejects with the raised Error.
    public copy( value: string ) : Promise<string> {
        var promise = new Promise(
            ( resolve, reject ) : void => {
                var textarea = null;
                try {
                    // In order to execute the "Copy" command, we actually have to have
                    // a "selection" in the currently rendered document. As such, we're
                    // going to inject a Textarea element and .select() it in order to
                    // force a selection.
                    // --
                    // NOTE: This Textarea is being rendered off-screen.
                    textarea = this.dom.createElement( "textarea" );
                    textarea.style.height = "0px";
                    textarea.style.left = "-100px";
                    textarea.style.opacity = "0";
                    textarea.style.position = "fixed";
                    textarea.style.top = "-100px";
                    textarea.style.width = "0px";
                    this.dom.body.appendChild( textarea );
    
                    // Set and select the value (creating an active Selection range).
                    textarea.value = value;
                    textarea.select();
                    // Ask the browser to copy the current selection to the clipboard.
                    this.dom.execCommand( "copy" );
                    resolve( value );
                } finally {
                    // Cleanup - remove the Textarea from the DOM if it was injected.
                    if ( textarea && textarea.parentNode ) {
    
                        textarea.parentNode.removeChild( textarea );
                    }
                }
            }
        );
        return( promise );
    }
    }
    

    Import both in the app.module.ts and then you can reference it in html with something like this:

    <p>
            <button [clipboard]="value1.innerHTML.trim()">
                Copy Text
            </button>
            <span #value1>
                Hello World!
            </span>
        </p>
    
    0 讨论(0)
提交回复
热议问题