RSS
 

AngularJS Auto-Focus Input After Router Template is Loaded in SPA

14 Oct

It’s been just a little while (oh, only about 3.5 years) since I last published any new posts here. Too busy.

At the moment I’ve been delving head-first into some modern frameworks like¬†AngularJS and Bootstrap, so I plan to document things I learn along the way that I think will help other developers also new to these technologies who might come up against some of the same issues or who might just find interesting the things I’m discovering.

Without further ado, this is my first of such posts, which is a little more advanced than just starting to learn everything from scratch, but I do plan to back-track and cover more in future posts the basics of using AngularJS.

If you’re developing a Single Page Application (SPA) with Angular, you may find that loading an HTML fragment with a form input that should be auto-focused might not work. Assuming you’ve already set up ngRoute to dynamically control the routing of your application, the simplest way I came up with to set focus on an input after ensuring the HTML template is fully loaded is to define a callback for $routeChangeSuccess which is invoked after the route has finished changing. The best place to respond to that event is in a run block, since it’s an application-wide action we’re taking. The trick is that the DOM may still not be ready for you to set focus at that point, but setting focus inside a $timeout will ensure the $digest loop has ended.

The other, more obvious decision was to ensure the input I want to auto-focus has the “autofocus” attribute so it can be targeted using a simple jQuery selector. Below is a bit of sample code demonstrating what I just described with comments, so hopefully it’s all pretty obvious to you (and it should be if you’re using Angular yourself).

[GitHUB »]

<script>
// first thing's first; initialize the app
var app = angular.module('yourAppName', ['ngRoute']);// '

//... do other things like set up your routing (not covered here)

// set up a Run Block
app.run(function _forceAutofocus($rootScope, $timeout) {

  // tell Angular to call this function when a route change completes
  $rootScope.$on('$routeChangeSuccess', function() {
    // we can't set focus at this point; the DOM isn't ready for us

    // instead, we define a callback to be called after the $digest loop
    $timeout(function(){
      // once this is executed, our input should be focusable, so find (with jQuery)
      // whatever is on the page with the autofocus attribute and focus it; fin.
      $('[autofocus]').focus();
    });
  });

});
</script>

 

4,005 views

Tags: , , ,

Leave a Reply