Detect Ctrl + C and Ctrl + V in an input from browsers

24,169

Solution 1

You simply can do who : for information this code manage all mac user who user CMD instead of ctrl

@HostListener('window:keydown',['$event'])
onKeyPress($event: KeyboardEvent) {
    if(($event.ctrlKey || $event.metaKey) && $event.keyCode == 67)
        console.log('CTRL + C');
    if(($event.ctrlKey || $event.metaKey) && $event.keyCode == 86)
        console.log('CTRL +  V');
}

If you want to detect other kind of shortcut :

  • event.ctrlKey
  • event.altKey
  • event.metaKey (Aka Cmd for mac user)

Online sample

--- UPDATE AFTER COMMENT ---

You may can do something like this

  ngOnInit() {
        this.bindKeypressEvent().subscribe(($event: KeyboardEvent) => this.onKeyPress($event));
    }

    onKeyPress($event: KeyboardEvent) {
        if(($event.ctrlKey || $event.metaKey) && $event.keyCode == 67)
            console.log('CTRL + C');
        if(($event.ctrlKey || $event.metaKey) && $event.keyCode == 86)
            console.log('CTRL +  V');
    }

    private bindKeypressEvent(): Observable<KeyboardEvent> {
        const eventsType$ = [
            fromEvent(window, 'keypress'),
            fromEvent(window, 'keydown')
        ];
        // we merge all kind of event as one observable.
        return merge(...eventsType$)
            .pipe(
                // We prevent multiple next by wait 10ms before to next value.
                debounce(() => timer(10)),
                // We map answer to KeyboardEvent, typescript strong typing...
                map(state => (state as KeyboardEvent))
            );
    }

or if is not working, just :

private bindKeypress(): Observable<KeyboardEvent> {
    const typeOfEvent = this.deviceService.getKeybordEvent();
    fromEvent(window, typeOfEvent)
    .pipe(
        // We map answer to KeyboardEvent, typescript strong typing...
        map(state => (state as KeyboardEvent))
    );
}

Where this.deviceService.getKeybordEvent(); is method who return type of event base on User Agent. massive list of user agent can be find here

Solution 2

Angular provides high level API for listening to key press combinations. Check out the following example.

ctrl-keys.directive.ts

import { Directive, Output, EventEmitter, HostListener } from '@angular/core';

@Directive({
  selector: '[ctrlKeys]',
})
export class CtrlKeysDirective  {
  @Output() ctrlV = new EventEmitter();
  @Output() ctrlC = new EventEmitter();

  @HostListener('keydown.control.v') onCtrlV() {
    this.ctrlV.emit();
  }

  @HostListener('keydown.control.c') onCtrlC() {
    this.ctrlC.emit();
  }
}

Usage

import { Component } from '@angular/core';

@Component({
  selector: 'my-app',
  template: `
  <input ctrlKeys (ctrlV)="onCtrlV()" (ctrlC)="onCtrlC()" >
  `,
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  onCtrlV() {
    console.log('ctrlV pressed')
  }

  onCtrlC() {
    console.log('ctrlC pressed')
  }
}

Live demo

Solution 3

Just add this to any component. When the user performs the key combination Ctrl +s it will print 'Save Performed'

@HostListener('document:keydown.control.s', ['$event']) onKeydownHandler(event: KeyboardEvent) {
    console.log('Save Performed');
    event.preventDefault();
}

If you want Ctrl +v replace the 's' in 'document:keydown.control.s' with 'v'.

Solution 4

Instead of monitoring the key events for copy and paste commands, I suggest handling the clipboard events (copy, cut, paste). In addition to taking care of the various shortcuts used on different platforms, it also detects the clipboard operations initiated with the context menu. Please note that the paste event can be cancelled with e.preventDefault(). You can see the code at work in this stackblitz.

@HostListener('copy', ['$event'])
onCopy(e: ClipboardEvent) {
  ...
}

@HostListener('paste', ['$event'])
onPaste(e: ClipboardEvent) {
  let clipboardData = e.clipboardData || window.clipboardData;
  let pastedText = clipboardData.getData('text');
  ...
}

Solution 5

Firstly import HostListener and create a method to listen to keyup event. Also, use ctrlKey because keycode is deprecated.

import { HostListener} from '@angular/core';

    @HostListener('window:keyup', ['$event'])
       keyEvent(event: KeyboardEvent) {
          if (event.ctrlKey) {
              if (event.key === 'c') {
                 console.log('ctrl c');         
              }      
             else if (event.key === 'v') {
                 console.log('ctrl v')
              }
      }
    
Share:
24,169
Mario Ramos García
Author by

Mario Ramos García

Updated on January 28, 2022

Comments

  • Mario Ramos García
    Mario Ramos García over 2 years

    I am using the direct following and I do not detect the copy and paste with the keys inside the input, would someone know how? Thank you!

    export class OnlyNumberDirective {
        // Allow decimal numbers. The \, is only allowed once to occur
        private regex: RegExp = new RegExp(/[0-9]+(\,[0-9]{0,1}){0,1}$/g);
    
        // Allow key codes for special events. Reflect :
        // Backspace, tab, end, home
        private specialKeys: Array<string> = [ 'Backspace', 'Tab', 'End', 'Home', 'Delete', 'Del', 'Ctrl', 'ArrowLeft', 'ArrowRight', 'Left', 'Right' ];
    
        constructor(private el: ElementRef) {
        }
    
        @HostListener('keydown', [ '$event' ])
        onKeyDown(event: KeyboardEvent): string {
            // Allow Backspace, tab, end, and home keys
            if (this.specialKeys.indexOf(event.key) !== -1) {
                return null;
            }
    
            // Do not use event.keycode this is deprecated.
            // See: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode
            let current: string = this.el.nativeElement.value;
            // We need this because the current value on the DOM element
            // is not yet updated with the value from this event
            let next: string = current.concat(event.key);
            if (next && !String(next).match(this.regex)) {
                event.preventDefault();
                return null;
            } else {
                return next;
            }
        }
    }