【问题标题】:Detect Ctrl + C and Ctrl + V in an input from browsers在来自浏览器的输入中检测 Ctrl + C 和 Ctrl + V
【发布时间】:2018-09-29 22:22:13
【问题描述】:

我正在使用直接跟随,我没有检测到输入内的键的复制和粘贴,有人知道吗?谢谢!

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

【问题讨论】:

    标签: angular directive keyboard-events onkeydown


    【解决方案1】:

    您可以简单地执行谁:此代码管理所有使用 CMD 而不是 ctrl 的 mac 用户

    @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');
    }
    

    如果您想检测其他类型的快捷方式:

    • event.ctrlKey
    • event.altKey
    • event.metaKey(Mac 用户的又名 Cmd)

    Online sample

    --- 评论后更新 ---

    你可以这样做

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

    或者如果不工作,只是:

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

    其中this.deviceService.getKeybordEvent(); 是返回基于用户代理的事件类型的方法。 massive list of user agent can be find here

    【讨论】:

    • 查看我的答案,了解处理此问题的角度方式:)
    • 和你一起回答我学到了新东西,谢谢分享。在@Mario 的情况下,由于他必须管理许多其他短代码,我认为我的方法会更容易使用。
    • 完美运行,谢谢!问题是我也需要它在 Internet Explorer 中为我工作,但它在那里不起作用。
    • 意味着您在OnlyNumberDirective 中的方法永远不会调用?如果是的话,试着玩一下keypresskeyup,凭记忆我已经尝试过这个问题。
    • 是的,它被调用了,但是对于每个浏览器它是不同的。
    【解决方案2】:

    Angular 提供了用于监听按键组合的高级 API。看看下面的例子。

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

    用法

    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

    【讨论】:

      【解决方案3】:

      只需将此添加到任何组件。当用户执行组合键 Ctrl +s 时,它将打印“Save Performed”

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

      如果你想要 Ctrl +v 将 'document:keydown.control.s' 中的 's' 替换为 'v'。

      【讨论】:

        【解决方案4】:

        我建议不要监视复制和粘贴命令的关键事件,而是处理剪贴板事件(copycutpaste)。除了照顾不同平台上使用的各种快捷方式外,它还检测使用上下文菜单启动的剪贴板操作。请注意paste 事件可以用e.preventDefault() 取消。您可以在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');
          ...
        }
        

        【讨论】:

          【解决方案5】:

          首先导入 HostListener 并创建监听 keyup 事件的方法。 也使用 ctrlKey 因为 keycode 已弃用。

          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')
                        }
                }
          

          【讨论】:

          • 这是最好的答案,因为它可以粘贴到原始指令中并工作
          【解决方案6】:
          @HostListener('document:keydown.control.c', ['$event'])
              onKeyDown(e) {
                  e.preventDefault();
              }
          
          @HostListener('document:keydown.control.v', ['$event'])
              onKeyDown(e) {
                  e.preventDefault();
              }
          

          【讨论】:

          • 正如目前所写,您的答案尚不清楚。请edit 添加其他详细信息,以帮助其他人了解这如何解决所提出的问题。你可以找到更多关于如何写好答案的信息in the help center
          • 虽然此链接可能会回答问题,但最好在此处包含答案的基本部分并提供链接以供参考。如果链接页面发生更改,仅链接答案可能会失效。 - From Review
          猜你喜欢
          • 2011-02-23
          • 2015-12-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-09-27
          • 2016-01-06
          • 2017-07-31
          相关资源
          最近更新 更多