I love keyboard shortcuts in web apps. There is nothing better than being able to quickly navigate a UI without ever needing to touch the mouse. On my current project, we are building keyboard shortcuts into an internal tool to help boost productivity. We have a rather simple and elegant solution using AngularJS and Mousetrap so I thought I would share some of the details.
To start, AngularJS is simply awesome. We are learning more and more of the framework everyday and it continues to grow on us. We are using a powerful feature called directives to apply our keyboard shortcuts. Directives are great because they are easy to start using but provide a powerful API to handle complex scenarios.
Although we could devote an entire post to directives I will try to sum them up succinctly. Directives allow you to teach HTML new tricks by creating your own custom elements and attributes. When a directive is executed it is able to manipulate the DOM or apply behavior to your application. This provides the perfect hook for us to wire up a keyboard shortcut.
The basic idea is that when a user presses a certain key sequence we will invoke a specified controller method. We can provide both the key sequence and the controller method as attributes of the directive. Let’s see what our final markup looks like so we have a better idea of where we are headed:
<keybinding on="g i" invoke="gotoInbox()" />
We will be defining a new element, keybinding, which has two custom properties of on and invoke. When a user presses the letter “g” followed by the letter “i” the method will be called on the current controller. The relevant directive code is below, but there is a full working example available on JSFiddle.
app.directive('keybinding', function () { return { restrict: 'E', scope: { invoke: '&' }, link: function (scope, el, attr) { Mousetrap.bind(attr.on, scope.invoke); } }; });
The directive is doing a couple of things. First, it is defining an isolate scope with a method called invoke. This allows us to pass in a function reference as an attribute in the markup. Next, our linking function is registering the key sequence with Mousetrap and providing the invoke function as the callback. Again, if you are new to directives you will want to consult the developer guide to gain an understanding about the code. I also recommend this egghead video if you are new to isolate scopes.
A few caveats:
- The directive is being restricted to elements (restrict: ‘E’) which is not supported in older browsers. Using attributes is recommended for supporting older browsers, but for a simple demo I think using elements makes the markup easier to understand.
- These shortcuts are global in the application! Even though I created these to be placed within a controller context, they will execute regardless of which element has focus in the web page.
- Mousetrap is an awesome project and a major reason the directive code is so small!
Hopefully this is helpful as a learning tool for directives. We would love to hear how others are handling keyboard shortcuts with AngularJS. Please feel free to leave us comments and thanks for reading!