pass parameters to backbone fetch url to deal with a non-standard api

mheavers picture mheavers · Oct 29, 2014 · Viewed 7.9k times · Source

I am trying to manipulate backbone's fetch method to to deal with a bit of a non-standard api. The way the api works is as follows:

api/products/[page]?param1=val&param2=val

ex:

api/products/2?budget=low&categories=all

would be equivalent to getting the second page of results for which the budget is low and all categories are included.

I can pass the parameters after the query string just fine through the format:

self.productsItemsCollection.fetch({ success : onDataHandler, dataType: "json", data: { budget: 'low', categories: 'all' } });

but I'm not sure what to do about the pagination, since it comes before the ? question mark.

Here is how the collection is set up:

define([
  'underscore',
  'backbone',
  'models/products/ProductsItemsModel'
], function(_, Backbone, ProductsItemsModel){

  var ProductsItemsCollection = Backbone.Collection.extend({

      model: ProductsItemsModel,

      initialize : function(models, options) {}, //MH - need to pass filters to this function

      url : function() {
        return '/api/products/'; //MH - need to pass page number to be appended to this url
      },

      parse : function(data) {
        debugger;
        return data.items;
      }

  });

  return ProductsItemsCollection;

});

How do I include the pagination in backbone's fetch command given this api URL structure?

Answer

Christopher picture Christopher · Oct 29, 2014

You're on the right track in that Backbone can use the return value of a function as its 'url' value. What I personally would do, is set a page property on the collection (referenced through something like this.page), and include that in the output of the url function.

initialize: function() {
  this.page = 1; // Or whatever the default should be
},
url: function() {
  return '/api/products/ + this.page;
}

The problem then becomes updating the page property, which can be as simple as 'ProductsItemsCollection.page = 2;'. Personally, I would also add a second fetch method to wrap the page update and fetch into a single method call.

fetch2: function(page, options) {
  if (page) {
    this.page = page;
  }
  return this.fetch(options);
}