Skip to content

Instantly share code, notes, and snippets.

@OscarGodson
Created November 13, 2013 17:08
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save OscarGodson/239bc11a4e8c2b46faad to your computer and use it in GitHub Desktop.
Save OscarGodson/239bc11a4e8c2b46faad to your computer and use it in GitHub Desktop.

I have a sidebar that pops in with form. It has a URL for it since it's so commonly used. Going to app.com/foo/add would load the page and open the sidebar. Another view, TopMenu, has a button to open the sidebar. My question: who triggers the URL change? Should RightSidebar change the URL with Backbone.navigate (w/o trigger) or should the button change the URL and call the RightSidebar's open method?

@mxriverlynn
Copy link

any time you have multiple points of entry for the same behavior, you need to encapsulate that behavior's kick-off in to a single thing... an object, a function, a single line of code... whatever that thing is, it needs to be the one thing that is called in order to produce the desired behavior and state of the application.

this often means you have to do a lot of prep work to get the application in to a state where that one thing can be called (http://lostechies.com/derickbailey/2012/02/06/3-stages-of-a-backbone-applications-startup/) but once you're there, you just call that one thing and the application puts itself in to the expected state with the expected behavior.

here's a simple example:

var MyRouter = Backbone.Router.extend({

  routes: {
    "/foo": "foo"
  },

  foo: function(){
    myController.doFoo();
  }

});

var MyView = Backbone.View.extend({

  events: { 
    "click #foo": "fooClicked"
  },

  fooClicked: function(e){
    e.preventDefault();
    this.trigger("do:foo");
  }

});

var myController = {

  doFoo: function(){
    // do stuff here, put the app in to a specific state, show new views, etc.
  },

  show: function(){
    var view = new MyView();
    view.on("do:foo", this.doFoo, this);
  }

};

in both cases (using the router or clicking the DOM element), the code all comes back to the doFoo function. this is the one place in the application that knows how to put the app in to the "foo" state - in your case, to put sidebar in place and put the route in the URL as expected. then it doesn't matter what code kicks off the doFoo process / app state. it could be a router, a button in a menu, a websockets event, or image recognition technology from a webcam. when the doFoo function is called, the app moves in to the right state and does it's thing, including setting the URL.

of course this gets complicated when you start talking about very large apps. in very large apps, you need to partition your apps based on context, to keep things sane. sometimes it will make sense for a butotn click to just call a method on an object and the app is good to go. but sometimes the feature being requested is in a completely different context, with a completely different layout in the app. in these cases, it's often easier to have a button click call router.navigate("foo", true)" to force the route handler to fire... or just use a link with the real url in the link. but in the end, the same principle applies. no matter how many entry points there are, you only need to call thedoFoo` function in order to get the app into the right state, with the right URL in the address bar.

@OscarGodson
Copy link
Author

Super awesome. Think I'm doing the "right" thing then.

TopMenu

app.view.TopMenu = Backbone.View.extend({
  events: {
    'click .add-button': 'addFoo'
  },
  el: '.toolbar',
  addFoo: function() {
    app.panels.RightSidebar.open();
  }
});

RightSidebar

app.view.RightSidebar = Backbone.View.extend({
  events: {},
  subviews: {},
  el: '#right-sidebar',
  initialize: function() {
    // ... initialize snap.js and stuff
  },

  open: function () {
    app.router.navigate("/foo/add");
    this.snapper.open('right'); // Snap.js
  }

  close: function () {
    window.history.back();
  }
});

@techwraith
Copy link

If it has a route, why not just navigate to that route and have the route handle the opening and closing?

@OscarGodson
Copy link
Author

@techwraith you mean like app.router.navigate('foo/add', {trigger: true})? I've read all over trigger is bad and causes issues. @derickbailey has written about it a few times.

If you simply mean make an html link to foo/add, that would work as it is now, but causes a full page refresh since it's pushState, not hashes. If you mean navigate minus the trigger, this would just change the URL and the app would ignore this.

If you mean something other than those three things or a way to make it better, let me know.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment