I have the following route in my Backbone router:
'surveys/:surveyId?:opts': 'SurveyList:Selected'
And the following handler that captures any route and republishes it on a message bus for my views to handle:
this.on('route', function() {
PubSub.publish(Events.RouteChanged, {
route: arguments[0],
options: arguments[1]
});
});
When the router matches the route surveys/myTestId123?pageNum=2
, the expected behaviour is that arguments[1]
would be an array of 2 arguments: myTestId123
and pageNum=2
. However, it is actually an array with 3 arguments - the two aforementioned ones and a null
value as the third. I narrowed this down to the _extractParameters
method, which matches the url fragment against a regular expression. In this case, the regular expression is /^surveys\/([^\/?]+)(?:\?([^\/?]+))?(?:\?([\s\S]*))?$/i
.
Interestingly enough, I get the correct parameters when the route is surveys/:surveyId
, which in turn produces this regex: /^surveys\/([^\/?]+)(?:\?([\s\S]*))?$/i
.
Here is a fiddle showing the problem in action.
Is this a problem with the regex that Backbone creates from my route, or a problem with the route itself?
I think I've just discovered the answer. It looks like Backbone already does what I'm trying to do. If I have the route surveys
, it also provides a null
parameter. However, the regex it creates is as follows:
/^surveys(?:\?([\s\S]*))?$/i
This appears to already match querystring parameters, which explains why the shorter route works in my example above. Those clever people at Backbone were one step ahead of me.
Update:
From the Backbone v1.1.1 change log:
Backbone Routers now handle query params in route fragments, passing them into the handler as the last argument. Routes specified as strings should no longer include the query string ('foo?:query' should be 'foo').