A Bit of Routing Confusion

So, I was working on an angular app, and just when I thought I’d successfully implemented my new poll page, the wrong page kept loading on the page. Frustration ensued until I finally realize what was happening. It was loading the wrong page because I was telling it to load the wrong page. The culprit code is show below:


.config(function ($routeProvider) {
  $routeProvider
  .when('/polls/:id', {
    templateUrl: 'app/poll/show.html',
    controller: 'PollShowCtrl'
  })

  .when('/polls/new', {
    templateUrl: 'app/poll/new.html',
    controller: 'PollCreateCtrl'
  })

});

The way the router works is like this: It takes the path and then chugs along through the routes until it sees one that matches the pattern present in the path. When you use parameters in the route like :id that I have above, that acts sort of like a wild card. the route assumes that anything that comes after ‘/polls/’ must be :id. It has no way of knowing that when I send in ‘/polls/new’ that new is not the parameter :id. So it will never reach the ‘/polls/new’ route. To fix this all you have to do is switch the order of your routes like so:


.config(function ($routeProvider) {
  $routeProvider

  .when('/polls/new', {
    templateUrl: 'app/poll/new.html',
    controller: 'PollCreateCtrl'
  })
  .when('/polls/:id', {
    templateUrl: 'app/poll/show.html',
    controller: 'PollShowCtrl'
  })
});

Since the first route only matches if the path is exactly ‘/polls/new’ this will now work both for the case of trying to go to the new poll page and also to go to the route that takes the :id as the value immediately after ‘/polls/’. The moral of the story here is to always start with your most specific routes first and then move on to more general routes. This ensures that you don’t accidentally match a route that just happens to be too broad.

Solving Problems I’ve Already Solved

Yesterday, I was working on a small, single page website, and I needed a way to filter the events on the page using a live-update search (results change as you type). Quite some time later I got something that resembled a working solution. Strutting proudly, I handed my laptop to my fiance and said, “Try this out!” expecting glorious praise and much applause. Instead, I got  “Why does it do that?”

Of course, she was absolutely right to question what it was doing (she usually is right). Firstly, I hadn’t really implemented a live search (you had to hit the enter key to update the results). Secondly, if you wanted to make all of those sad, hidden non-match entries reappear, you had to clear out the search box and hit Enter again.

I returned to my desk slightly deflated and resigned to the fact that I’d need to start over from scratch. The changes I’d need to make already zipping around in my head, I realized I’d already solved this problem before. I’d written a little web app that had exactly the search functionality I wanted to use on this page. I couldn’t believe that I’d forgotten about it.

I sat down at my desk, brought up the previous code, did a bit of copying and pasting, and in about 10 minutes, with very little modification, I had exactly the functionality I’d spend the last hour and a half trying to implement. For anyone who’s interested, here’s the little solution I’d forgotten I’d already created.


$('#event-search').on('keyup', function(){
  var query = $(this).val();
  var filter = new RegExp('.*' + query + '.*','i');

  $('.event').each(function(i,value) {
    if ($(this).children().text().match(filter)) {
      $(this).show();
    }else {
      $(this).hide();
    }
  });
});

It’s simple and straight-forward, and I’m not entirely sure why I didn’t think of it the second time, but the point is, I shouldn’t have had to think of it again. Hopefully, the next time I sit down to write some code, I’ll remember I don’t always have to start from scratch even if managing to remember this lesson means my fiance will miss my exasperated look when I realize “Hey, I think I’ve done this already” after an hour of work.