2

I have an endpoint in my application that returns data based on the given query string. The query string can (and often has to) contain duplicate keys, for example /api/entities/related?filter1=val1&filter1=val2&filter2=val3 to identify two filters of type filter1. Flask deals with this nicely, for example when doing request.args.to_dict, I would get {'filter1': ['val1', 'val2'], 'filter2': 'val3'}.

My question is how to achieve the same thing with Backbone when fetching a collection from an endpoint. Currently I might have

this.fetch({data: {'filter1': 'val1', 'filter1': 'val2', 'filter2': 'val3'}});

Since duplicate keys will override each other in javascript objects, my filter1 value will end up being val2. However, when doing

this.fetch({data: {'filter1': ['val1', 'val2'], 'filter2': 'val3'}});

the url ends up being /api/entities/related?filter1%5B%5D=val1&filter1%5B%5D=val2, which at least does use two identical keys but obviously does not work.

Is this an encoding problem or should I approach it differently?

Elise
  • 5,086
  • 4
  • 36
  • 51
  • you should communicate with your endpoint with json payloads , i.e. use POST requests with a json body when necessary, instead of dealing with messed-up url encodings in the query string , the simpler the better. – mpm Jan 31 '13 at 17:10
  • 1
    I believe that is the standard way to encode an array in an url, which decodes back to this: `decodeURIComponent($.param({filter1: ['val1', 'val2']})); // outputs: "filter1[]=val1&filter1[]=val2"`. I can't find much documentation on this, but this SO response agrees (plus, I trust jQuery's $.param()): http://stackoverflow.com/questions/40568/square-brackets-in-urls/1718238#1718238 – robmisio Jan 31 '13 at 21:25

2 Answers2

1

You can pass a querystring with duplicate keys using an Array as a value.

this.fetch({ data: $.param({ filter1: ['value1','value2']}) });

Or, you can always set the URL like this with querystring params.

var MyModel = Backbone.Model.extend({
  "url": function() {
      return '/' + encodeURI('?filter1=' + val1 + '&filter1=' + val2);
  }
});

If you have to change params all the time, you can do something like and work with it directly:

this.model.destroy({
    url: '/' + encodeURI('?filter1=' + val1 + '&filter1=' + val2)              
});

If you have multiple concrete params (meaning the values changes but the key are static) that changes per fetch (ie: search), you can check out a paging implementation on Gist that might be useful for your situation whatever it may be.

Hope this helps.

Dennis Rongo
  • 4,611
  • 1
  • 25
  • 25
  • Thanks -- I did try using $.param(), but that still results in the same weird url. Your second suggestion is what I initially did but I have to occasionally refetch the data using different parameters and it didn't make sense to update the url every time. – Elise Jan 31 '13 at 17:39
  • Changed and tested the first code above to pass in multiple values for 1 key. See my updated response. – Dennis Rongo Jan 31 '13 at 19:52
0

Thanks for everyone's input.

Apparently the data you pass does not have to be an object -- I found that the easiest way in my case was to pass a string ('filter1=val1&filter2=val2') to fetch() and that worked perfectly.

Elise
  • 5,086
  • 4
  • 36
  • 51
  • Your server framework should (de-)serialize something like ?filter[]=a&filter[]=b into a dictionary/hash with 'filter' as the key and ['a', 'b'] as the value. It probably depends on your server framework what the syntax looks like. The example I provided works in Rails – ur5us Jul 07 '13 at 09:56