0

what-is-angular2-way-of-creating-global-keyboard-shortcuts

Only that im interested in making the shortcuts binded to a specific element (or a container if you will). The shortcut should only work the user focus is in the element or one of his children, and when the element is removed from the dom, the bindings naturally should remove with it.

I have found some way of doing these which I find not very clean:

/**
* Created by Ziv on 5/23/2016.
*/
import {Injectable} from "angular2/core";

@Injectable()
export class KeyBoardService {

public registerKeyStrokeForElemet(
    strKeyStroke: string,
    fnCallBack: () => void,
    fnIsButtonAvailable: () => boolean,
    element: any,
    bShouldEffectOnlyInContainer: boolean,
    functionThisContext: any): void {

    // Adding tab index property to the container so the events will be raised only when
    // the container is focused
    jQuery(element).prop("tabindex", 1);

    jQuery(element).css("outline", "none");

    jQuery(element).bind(
        'keystrokes', {
            keys: [strKeyStroke]
        }, (e) => {
            // Checking if this event should only happen when the div container is focused
            if (!bShouldEffectOnlyInContainer || jQuery(e.target).is("div")) {
                if (typeof fnIsButtonAvailable !== "function" || fnIsButtonAvailable.apply(functionThisContext, event)) {
                    e.preventDefault();

                    fnCallBack.apply(functionThisContext);
                }
            }
        }
    );

    // If the event should effect all the elements inside the container too,
    // there is a special case when events in jquery keystroke library ignored text inputs.
    // the solution offered by the libraray author is to assign thoose events to them inputs
    // explicitly, which is what were gonna do next
    if (!bShouldEffectOnlyInContainer)
    {
        jQuery(element).find(
                "textarea, :text"
            ).bind(
            'keystrokes',
            {
                keys: [strKeyStroke]
            },
            (e) => {
                if (typeof fnIsButtonAvailable === "function" || fnIsButtonAvailable.apply(functionThisContext, event)) {
                    e.preventDefault();

                    fnCallBack.apply(functionThisContext);
                }
            }
        );
    }
}

}

It relies on using jquery-keystrokes jquery keystrokes Which is a bit old, and generally I find using to much jquery in an angular 2 app pretty dirty, so I am looking for the "angular way" to achieve this

Community
  • 1
  • 1
Ziv Glazer
  • 786
  • 2
  • 8
  • 24
  • Refer http://stackoverflow.com/questions/35600685/what-is-angular2-way-of-creating-global-keyboard-shortcuts-a-k-a-hotkeys It might helps :) – Hardipsinh Jadeja May 30 '16 at 10:39
  • I refered to that question in the start of my own question and explained that the solutions offered there don't seem to solve what im trying to achieve – Ziv Glazer May 30 '16 at 10:47

1 Answers1

2

This should get you started...

To listen for keystrokes on a DOM element (e.g., a div) you can create an attribute directive that uses

import {Component, Directive, Input, HostBinding, HostListener} from '@angular/core';

@Directive({selector: '[catchkeys]'}) 
export class CatchKeys {
  // add tabindex attribute so host element (e.g., a div) will receive keyboard events
  // https://stackoverflow.com/questions/10722589/how-to-bind-keyboard-events-to-div-elements
  @HostBinding('tabindex') tabIndex = 1;
  @HostListener('keyup', ['$event'])
  onKeyUp(kbdEvent) {
    console.log(kbdEvent);
  }
}

@Component({
  selector: 'child',
  template: `<div catchkeys>child: {{msg}}
      <div>child element</div>
    </div>`,
  directives: [CatchKeys]
})
class Child {
  @Input() msg:string;
}

Plunker


To filter specific keys, pass a list into the CatchKeys directive:

<div catchkeys="someListOfKeys">

Then modify the directive:

@Input() catchkeys:string;  // or maybe use an Array 
ngOnInit() {
  console.log(this.catchkeys);
}
// use this.catchkeys in the onKeyUp() method to filter
Community
  • 1
  • 1
Mark Rajcok
  • 362,217
  • 114
  • 495
  • 492
  • Sounds like what I was looking for, thanks for your reply :) Only thing i'm not sure about from your sample is how do you filter the event to only respond to the keys you passed from the outside, but I'll try it soon and update the question – Ziv Glazer May 31 '16 at 20:14
  • @ZivGlazer, I don't think you can filter the event. I think you can only filter inside the event handler. – Mark Rajcok Jun 16 '16 at 16:05