Detect Ctrl + C and Ctrl + V in an input from browsers
Asked Answered
E

6

21

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;
        }
    }
}
Exorcism answered 19/4, 2018 at 12:3 Comment(0)
E
28

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

Evanston answered 19/4, 2018 at 12:13 Comment(8)
Check out my answer for angular way of handling this problem :)Sermon
with you answer i have learn new thing, thanks for sharing us. On @Mario case, and because he have to manage many other short code, i think my approch will be easier to use.Evanston
It works perfectly, thank you! The problem is that I need it to work for me in Internet Explorer, too, and it does not work there.Killingsworth
Means your method inside OnlyNumberDirective is never call ? if yes, just try to play around keypress and keyup, by memory i already have experiment this issue.Evanston
Yes, it is called but for each browser it is different.Killingsworth
@MarioRamosGarcía i have update my answer, i hope this will help you to manage your issue.Evanston
deviceService? what is this btw?Scurrilous
@Vincent-cm according to the line fromEvent(window, typeOfEvent) i guess is service helper who return string like keypress keydown, to help to configure who UI react to user interaction.Evanston
S
17

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

Sermon answered 19/4, 2018 at 12:13 Comment(0)
R
6

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'.

Rambouillet answered 10/5, 2019 at 4:56 Comment(0)
C
3

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')
              }
      }
    
Cheerly answered 6/4, 2020 at 8:7 Comment(1)
This is the best answer because it can be pasted into the original directive and workStheno
C
2

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');
  ...
}
Cutin answered 19/4, 2018 at 13:49 Comment(3)
But this would only listen to copy & paste done using the mouse. You wont able to handle the values copied using ctrl+c & ctrl+v (keyboard)Nacreous
@HassanArafat - I don't know why you say that. When I test my Stackblitz project, it handles copy/paste with the mouse and with the keyboard shortcuts Ctrl+C and Ctrl+V. It works with all copy/paste events.Cutin
my bad. The issue was that I was also listening to keydown event which dont let onPaste event to be listened to. So, I replaced listening to keydown by keyupNacreous
R
0
@HostListener('document:keydown.control.c', ['$event'])
    onKeyDown(e) {
        e.preventDefault();
    }

@HostListener('document:keydown.control.v', ['$event'])
    onKeyDown(e) {
        e.preventDefault();
    }
Radioluminescence answered 20/10, 2021 at 6:46 Comment(2)
As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.Acidulate
While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - From ReviewJoey

© 2022 - 2024 — McMap. All rights reserved.