Saturday, May 19, 2012

ExtJS History is backwards

Ext JS's History navigation is backwards. I know why they did it that way (in the name of cross-browser compatibility), and most people, like balupton's history.js, get it wrong too.

In your app, you want to change the URL bar AFTER you navigate, not before.

Here's why:
  1. Your app should work without browser history manipulation, so you need some sort of navigation system in the first place
  2. You don't want to change the URL bar if the user doesn't want to leave the current form (because it's dirty)

Therefore, you need to try to navigate first, and only if it's successful, do you change the URL bar.

Unfortunately, Ext.History makes this impossible, as change() always fires after add(), no matter what you do (because there is a timer that polls the URL bar for changes every 50 ms).

HTML5 pushState and onpopstate do it correctly, in that calls to pushState() never fire onpopstate. onpopstate is only ever fired by the user, which is what you want.

Your navigation process should look something like this:

  • User is at "Tasks" screen, for example. URL is "#tasks"
  • User clicks the "Contacts" button or similar
  • Your app asks the current form if it is OK to navigate away (perhaps w a user confirmation dialog)
  • If not, do nothing. If ok, display the contact form. 
  • Update the URL bar to "#contacts", using pushState

  • URL bar is at "#contacts"
  • User hits the back button
  • URL bar is at "#tasks". onpopstate fires
  • App asks the Contacts form if it's ok to unload
  • If not OK, do nothing and change the URL bar back to "#contacts", usually with replaceState
  • If OK, load the tasks form

No comments:

Post a Comment