gustavotkg
gustavotkg

Reputation: 4399

Backbone.js in a not SPA application issues when browsing history

I started developing with Backbone.js recently. In this application I have a screen where I can filter a lot of rows by multiples filters, for instance: date, status, etc.

The problem is that it is not an SPA (Single Page Application), but it in fact a single page which makes use of Backbone.js. So, other pages does not make usage of this framework. Only in these two routes (/rows and /rows/search/:params).

There is not problem when I browse between these routes, it is loading and working perfectly. The problem occurs when I browse /login for example, which makes a full page refresh and then click on history back button. When I hit return button, I is shown the last JSON called by Model.fetch method.

I've tried some things, maybe I didn't got Backbone's way of fetching it.

First, I tried Backbone.history.start({root: '/rows'}); to tell app I'd like to pushState only from this path on. Same error occured.

So I though It could be the way I handled the pushState in View. So, I do this way:

App.View.Rows = Backbone.View.extend({
  el: $(document.body),
  events:{ // my events },
  initialize: function() {
    this.model = new App.Collection.Model();
    this.model.bind('reset', this.render, this);
  },
  submitForm: function(ev) {
    ev.preventDefault();
    this.search(ev);
    return false;
  },
  openFilters: function() {
    var el = this.el.find('div.box_content');
    if (!el.is(':visible')) el.slideDown();
  },
  resetFilters: function() {
    window.location.hash = "/rows";
  },
  populate: function(opts) {
    var opts = opts || (opts = {});
    if (this.lastFetch) this.lastFetch.abort();
    this.lastFetch = this.tasks.fetch({data: opts});
  },
  render: function() {
     // logic to render results
  },
  search: function(ev) {
    this.doSearch( this.getFilterOptions() );
  },
  getFilterOptions: function() {
    var opts = //get url params
    return opts;
  },
  doSearch: function( opts ) {
    window.location.hash = '/rows/search/' + $.param(opts);
  }
});

I also tried to change window.location.hash for Backbone.history.navigate, but the error still remained. Actually, Backbone.history.navigate was my first shot, so I changed to window.location.hash.

My collection is a normal one, only the url param is specified and search is done via query string.

So, guys, what could It be? Why when I history back it is showing me JSON instead of firing Backbone.js router? How can I solve this? Is it possible to have a Backbone.js in a single page instead of a SPA?

Upvotes: 3

Views: 820

Answers (1)

Johnny Oshika
Johnny Oshika

Reputation: 57512

Based on the additional info in your comments, it looks like /rows/search/foo is routing server-side to /rows?q=foo. Try turning off pushState.

use

Backbone.history.start()

instead of

Backbone.history.start({pushState: true})

If the behaviour is now fixed, then it's a server-side routing issue. If you still want to use pushState, you will need to make sure any URL that starts with "/rows" (e.g. /rows/search/foo) returns the same HTML as "/rows". This will of course mean that you'll need to use a different URL pattern for your ajax requests (e.g. /api/rows?q=foo instead of /rows?q=foo).

Upvotes: 1

Related Questions