Search code examples
javascriptbackbone.jsurlencodegithub-api

How to fetch a backbone collection without encoding the URL parameters?


We need to send request

https://api.github.com/search/repositories?q=angular+user:angular&order=desc

but in console request is

https://api.github.com/search/repositories?q=angular%2Buser%3Aangular&order=desc

The collection

var RepoCollection = Backbone.Collection.extend({
    url: 'https://api.github.com/search/repositories',

    initialize: function () {},

    fetch: function(options) {
        var params = {
            q:"angular+user:angular",
            order:"desc"
        };
        return Backbone.Collection.prototype.fetch.call(this, {
            data: $.param(params) 
        });
    }
});

For example:

Request: https://api.github.com/search/repositories?q=com%2Buser%3Attomashuk&order=desc

{
  "total_count": 0,
  "incomplete_results": false,
  "items": [

  ]
}

Request: https://api.github.com/search/repositories?q=com+user:ttomashuk&order=desc

{
      "total_count": 1,
      "incomplete_results": false,
      "items": [
        {
          "id": 104921385,
          "name": "CompanyOrganizer",
          "full_name": "ttomashuk/CompanyOrganizer",
          .........
          "score": 1.2680688
        }
      ]
    }

Solution

  • The jQuery documentation on $.param shows exactly what you're looking for:

    var myObject = {
      a: {
        one: 1,
        two: 2,
        three: 3
      },
      b: [1, 2, 3]
    };
    var recursiveEncoded = $.param(myObject);
    var recursiveDecoded = decodeURIComponent($.param(myObject));
    
    console.log("encoded:", recursiveEncoded);
    console.log("decoded:", recursiveDecoded);
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

    Which should output:

    encoded: a%5Bone%5D=1&a%5Btwo%5D=2&a%5Bthree%5D=3&b%5B%5D=1&b%5B%5D=2&b%5B%5D=3
    decoded: a[one]=1&a[two]=2&a[three]=3&b[]=1&b[]=2&b[]=3
    

    So you could fetch with:

    return Backbone.Collection.prototype.fetch.call(this, {
        data: decodeURIComponent($.param(params))
    });
    

    You should also pass any other options initially passed to fetch down to the original fetch call so your overriding is transparent:

    fetch: function(options) {
        options = options || {};
    
        // extend the passed data with the default
        options.data = decodeURIComponent($.param(_.extend({
            q: "angular+user:angular",
            order: "desc"
        }, options.data)));
    
        return Backbone.Collection.prototype.fetch.call(this, options);
    }