Search code examples
javascriptbackbone.jsurl-encoding

Backbone fetch url not formatting as expected


It is similar to backbone fetch URL data formatting error except that when trying the answer the URL looks like http://localhost?site:[Object%20Object]

My data:

options.data = { name:companyName}

Where company name would hold a value like "One, Two, Three". Without doing the encodeURIComponent, the query looks like http://localhost?name=One%2C+Two%2C+Three.

I would have expected it to look like http://localhost?name=One%2C%20Two%2C%20Three (note the %20 in the URL and the removal of +).

Just to be clear my code looks something like this:

 sync: function(method, model, options) {
    switch(method){
        case "read": {
              options.data = { name:options.data.name} //I only want to pass in a subset of properties for the query.
              //options.data = {encodeURIComponent(options.data.name)} //this returns [Object%20Object]
            }
            break;
        default:
            break;
    }
    Backbone.sync.apply(this, arguments);
}

I have tried processData: either being false or true for both scenarios.

Update

I'm currently getting around this by doing the following:

sync:function(method, model, options){  
    switch(method){  
        case "read":  
            options.url = this.url+"?name="+options.data.name  
            break;  
        default:
            break;
    }  
    Backbone.sync.apply(this, arguments);  
}  

That gets me my expected result I just can't believe that this is the answer and that backbone just cannot handle sequential special characters in a get request


Solution

  • A simple fetch like the following automatically use /test?name=One%2C%20Two%2C%20Three. encodeURIComponent is not needed.

    collection.fetch({
      data: {
        name: "One, Two, Three"
      }
    });
    

    var Collection = Backbone.Collection.extend({
      url: "test"
    });
    
    var collection = new Collection();
    
    collection.fetch({
      data: {
        name: "One, Two, Three"
      }
    });
    // request to /test?name=One%2C%20Two%2C%20Three
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.3.3/backbone-min.js"></script>

    From the jQuery ajax documentation:

    It is converted to a query string, if not already a string. It's appended to the url for GET-requests. See processData option to prevent this automatic processing. Object must be Key/Value pairs.

    If you can't pass it as an option to the fetch function, you should override the fetch function of the collection (or model) instead of the sync.

    var Collection = Backbone.Collection.extend({
      url: "test",
      fetch: function(options) {
        options = options || {};
        // example, extending the data object.
        options.data = _.extend({}, options.data, { name: this.companyName });
        return Collection.__super__.fetch.call(this, options);
      }
    });