0

Consider this URL:

domains.google.com/registrar#t=b

note:

#t=b

In this example, the variable "t" stores the current tab on the page where "b" is for billing.


How can I achieve query like parameters in backbone as shown above?

I understand Backbone has routes that support parameters in urls, but this is limited to when the data is in a hierarchy, for example: item/:id

But what about application settings that would not work well in a directory like structure?

The only solution I can think of is a custom parser and break up the key/values myself.

Any ideas?

seebiscuit
  • 4,905
  • 5
  • 31
  • 47
javajaba
  • 75
  • 2
  • 11
  • [The Backbone.js router](http://backbonejs.org/#Router-routes) is actually very strong, you can can use single placeholder, multiple placeholders to refrect hierachies and even use [RegularExpressions](http://backbonejs.org/#Router-route) for matching. Please take a look at the docs, try again and update your question if you still have troubles. – try-catch-finally Dec 25 '14 at 08:20

1 Answers1

2

Expanding on @try-catch-finally's comment, I'm going to show you how to create your own route with a simple RegEx pattern that will match your conditions.

Here's the regex we'll use:

^\w+?           # match one word (or at least a character) at the 
                # beginning of the route

[=]             # until we parse a single 'equals' sign

(               # then start saving the match inside the parenthesis

[a-zA-Z0-9]*    # which is any combination of letters and numbers

)               # and stop saving

Putting it all together the regex looks like: /^\w+?[=]([a-zA-Z0-9]*)/.

Now we set up our router,

var MyRouter = Backbone.Router.extend({
  initialize: function(options) {
    // Matches t=b, passing "b" to this.open
    this.route(/^\w+?(?<=[=])(.*)/, "testFn");
  },

  routes: {
      // Optional additional routes
  },

  testFn: function (id) {
      console.log('id: ' + id );
  }
});

var router = new MyRouter();
Backbone.history.start();

The TL;DR is that in the MyRouter.initialize we added a route that takes the regex above and invokes the MyRouter.testFn function. Any call to http://yourdomain.com#word1=word2 will call the MyRouter.testFn with the word after the parenthesis as a parameter. Of course, your word place setting could be a single character like in your question t=b.

Expanding your parameters

Say you want to pull multiple parameters, not just the one. The key to understanding how Backbone pulls your parameters is the capturing group (). A capturing group allows your to "save" the match defined within the parenthesis into variables local to the regex expression. Backbone uses these saved matches as the parameters it applies to the the route callback.

So if you want to capture two parameters in your route you'd use this regex:

^\w+?[=]([a-zA-Z0-9]*)[,]\w+?[=]([a-zA-Z0-9]*)

which simply says to expect a comma delimiter between the two parameter placeholders. It would match,

t=b,some=thing

More general route patterns

You can repeat the [,]\w+?[=]([a-zA-Z0-9]*) pattern as many times as you need. If you want to generalize the pattern, you cold use the non-capturing token (?: ... ) and do something like,

^\w+?[=]([a-zA-Z0-9]*)(?:[,]\w+?[=]([a-zA-Z0-9]*))?(?:[,]\w+?[=]([a-zA-Z0-9]*))?

The regex above will look for at least one match and will optionally take two more matches. By placing a ? token at the end of the (?: ... ) group, we say the pattern in the parenthesis may be found zero or one times (i.e. it may or may not be there). This allows you to set a route when you know you can expect up to 3 parameters, but sometimes you may want only one or two.

Is there a truly general route?

You may be asking yourself, why not simply use one greedy (?: ... ) group that will allow an unlimited number of matches. Something like,

^\w+?[=]([a-zA-Z0-9]*)(?:[,]\w+?[=]([a-zA-Z0-9]*))*

With this regex pattern you must supply one parameter, but you can take an unlimited number of subsequent matches. Unfortunately, while the regex will work fine, you won't get the desired result. (See, for example, this Question.)

That's a limitation of JavaScript. With repeating capturing-groups (i.e. the ([a-zA-Z0-9]*) capturing-group will repeat with every repetition of the (?: ... ) non-capturing-group) JavaScript only saves the last match. So if you pass a route like t=b,z=d,g=f,w=1ee, you'll only save 1ee. So, unfortunately you have to have an idea of what the maximum number of parameters your route should take, and manually code them into your regex pattern like we did above.

Community
  • 1
  • 1
seebiscuit
  • 4,905
  • 5
  • 31
  • 47