1

I'm building a web app using Backbone and Marionette with Ruby on Rails on the server.

The app works great, except for the back button of back browser (FF, Chrome, IE11) that breaks everything.

Here is a really simple example that reproduce the problem:

var TestApp = new Marionette.Application();

TestApp.addRegions({
 mainRegion: "#main-region"
});

TestApp.navigate = function(route, options){
 options || (options = {});
 Backbone.history.navigate(route, options);
};

TestApp.getCurrentRoute = function(){
 return Backbone.history.fragment
};

TestApp.on("start", function(){
 if(Backbone.history){
  Backbone.history.start();
  if(this.getCurrentRoute() === ""){
   this.navigate("foo");
   TestApp.MyApp.Show.Controller.ShowFoo();
  }
 }
});

TestApp.module("MyApp", function(App, TestApp, Backbone, Marionette, $, _) {
 App.Router = Marionette.AppRouter.extend({
  appRoutes: {
   "foo": "ShowFoo",
   "bar": "ShowBar",
   "baz": "ShowBaz"
  }
 });
 
 var API = {
  ShowFoo: function(){
   App.Show.Controller.ShowFoo();
  },
  ShowBar: function(){
   App.Show.Controller.ShowBar();
  },
  ShowBaz: function(){
   App.Show.Controller.ShowBaz();
  }
 };
 
 TestApp.addInitializer(function(){
  new App.Router({
   controller: API
  });
 });
});

TestApp.module("MyApp.Show", function(Show, App, Backbone, Marionette, $, _)
{
 Show.FooLayoutView = Backbone.Marionette.LayoutView.extend({
  template: "#templates-foo",
  tagName: "span"
 });
 Show.BarLayoutView = Backbone.Marionette.LayoutView.extend({
  template: "#templates-bar",
  tagName: "span"
 });
 Show.BazLayoutView = Backbone.Marionette.LayoutView.extend({
  template: "#templates-baz",
  tagName: "span"
 });

 var ContactsShowController = Marionette.Controller.extend({
  ShowFoo: function()
  {
   this.fooView = new Show.FooLayoutView();
   
   App.mainRegion.show(this.fooView);
  },
  ShowBar: function()
  {
   this.barView = new Show.BarLayoutView();
   
   App.mainRegion.show(this.barView);
  },
  ShowBaz: function()
  {
   this.bazView = new Show.BazLayoutView();
   
   App.mainRegion.show(this.bazView);
  }
 });
 Show.Controller = new ContactsShowController;
});

$(function() {
 TestApp.start();
});
<h1>Test the browser's back button.</h1>

<div id="main-region"></div>

<script type="text/template" id="templates-foo">
 <p>
  F O O
 </p>

 <p>
  <a href="#bar">-&gt; Bar</a>
 </p>
</script>

<script type="text/template" id="templates-bar">
 <p>
  B A R
 </p>

 <p>
  <a href="#baz">-&gt; Baz</a>
 </p>
</script>

<script type="text/template" id="templates-baz">
 <p>
  B A Z
 </p>

 <p>
  Press the back button on your browser. You should go back to BAR, but the view is not shown.
 </p>
</script>
The above snippet probably doesn't work directly, you'd need to include Backbone and MarionetteJS.

I'm using these versions of the librairies:

  • underscore.js 1.7.0
  • backbone.js 1.1.2
  • backbone.marionette.js 2.2.2

So, if you load the app, you should see "F O O", click the link for Bar, the click the link for Baz. You should now be on the last page showing "B A Z". Now click on the back button on your browser. The url should change back to #bar wich it does, but you should also see "B A R", but the #main-region is empty.

How can I fix this?

I'm open to update the libraries. And frankly, I'm also on the edge of throwing backbone and marionette in the trash and recoding everything in good old javascript + jQuery... But I,d prefer not to.

Thanks for any help.

Guillaume

1 Answers1

2

Update: Based on comments, it became evident that the culprit was a an add-on that came packaged with the OP's rails installation.

I suggested that he remove the rails/turbolinks libraryin his project, as it seemed to be interfering with proper page-reload.


Made a fiddle with your code and included the same libraries you posted. I didn't change a thing and it works like magic.

I also used jQuery 2.1.0 What's your version? See the fiddle.

seebiscuit
  • 4,905
  • 5
  • 31
  • 47
  • Thank you for the reply, but it did not help me. – Guillaume Grillon Labelle Jan 12 '15 at 22:44
  • Your fiddle works fine. I updated jquery-rails to version 4.0.3 and I am now using jquery2 in my application.js which is jQuery 2.1.3. If I execute bundle list, it gives me this http://www.filedropper.com/bundle-list And here is the complete code: http://www.filedropper.com/test-history I don't know this file hosting web site, so I hope it works well... I executed rake assets:clobber and rake assets:precompile, cleared my browser's cache, used an other browser. Nothing works :(, My teammates don't have more luck. – Guillaume Grillon Labelle Jan 12 '15 at 23:03
  • When I go back, both the url and the main-region appear properly, but the main-region get cleared after half a second. PS: Why are comments on stackoverflow so small? I had to split my comment into 3 plus a file... w/e Thank you – Guillaume Grillon Labelle Jan 12 '15 at 23:05
  • My anti-virus won't let me download files from the file host site you provided. I suggest your put up your project on GitHub. Are you getting any errors in the debugger console? – seebiscuit Jan 13 '15 at 01:39
  • Nope no errors, no exceptions, no nothing. I'll look into putting it on github tomorrow. – Guillaume Grillon Labelle Jan 13 '15 at 06:11
  • I have a hunch that your problem is two-fold. What would fit your observations is that on pressing `Back` your rails back-end is somehow reloading your page without doing a full reload, thus invoking `TestApp.start()`. However `this.getCurrentRoute()` in your `start` event does not return empty, and your app does not resolve any view. To test this put a `debugger` or `console.log` on the first line of the `start` event callback and see if the `start` event is being called on a `Back` press. – seebiscuit Jan 13 '15 at 11:54
  • Here is my project on GitHub : https://github.com/GuillaumeGrillonLabelle/test-history If I put a breakpoint on the line "if(Backbone.history){" it's only hit when I refresh the page by F5, when the app starts, not when I change pages or go back. – Guillaume Grillon Labelle Jan 13 '15 at 15:33
  • 1
    Noticed this https://github.com/GuillaumeGrillonLabelle/test-history/blob/master/app/views/layouts/application.html.erb#L5, see the documentation: https://github.com/rails/turbolinks. This may be messing with your links. You can make the view links (Foo, Bar, Baz) links non-turbolinked by doing something like `-> Bar` – seebiscuit Jan 13 '15 at 16:04
  • Thank you very much, I owe you many beers! Turbolinks, whatever it's supposed to do, it messes up my app. The data attribute did not help, but completely removing the library worked. I've read the doc of Turbolink and while it looks usefull, I can't see why my app would really need this, so I'll simply remove it. THANK YOU!!! I'd like to mark your comment as the answer, but I don't see how, stackoverflow is great yet weird :) – Guillaume Grillon Labelle Jan 13 '15 at 18:37