8

I'll walk through the problematic flow...

  • I load google.com (just as a starting point)
  • I goto app.com
  • I nav to app.com/projects
  • I nav to app.com/api/test (through window.location)
  • I see the raw JSON (good so far...)
  • I press back, url changes to app.com/projects but I still see the JSON.
  • I press back again, url changes to app.com but I still see the JSON.
  • I press back again, google.com loads.
  • I press forward, app.com loads fine... everything back to normal

What's odd, is I've observed this only when html5Mode = true in Webkit—firefox works as desired...

. . .

First, my server.coffee looks like this:

app.get '/partials/:partial', routes.partials
app.get '/api/test', api.test
app.get '*', routes.index

Basically, all requests load the index (which bootstraps Angular), with exception for a view/partial handler, and a test api route that responds with raw JSON.

. . .

(I'm using the ui-router module for managing nested views and UI states; it uses $urlRouterProvider, which is very similar to Angular's $routeProvider)

Second, my app.coffee looks like this:

app = angular.module('app', ['ui-router'])
.config([
    '$stateProvider'
    '$locationProvider'
    '$urlRouterProvider'
    ($stateProvider, $locationProvider, $urlRouterProvider)->
        $urlRouterProvider
            .when('/api/test', [
                '$window'
                '$location'
                ($window, $location)->
                    $window.location.href = '/api/test'
            ])
            .otherwise('/')
        $stateProvider
            .state 'home',
                url: '/'
                templateUrl: 'partials/index'
                controller: 'IndexCtrl'
            .state 'projects',
                url: '/projects'
                templateUrl: 'partials/projects'
                controller: 'ProjectsCtrl'
        $locationProvider.html5Mode(true).hashPrefix '!'
])

Since everything is async, I had to use $window to access window.location.href to trigger a page refresh so that the server would handle the route.

So my question, can I mix links that trigger page refreshes with Angular's html5Mode without breaking the back button? Is this just a Webkit bug, and/or is there a better way to do this?

Ideally, I'd have the application running off Angular—but things like the "about" or "contact" page (which have no need to be dynamic or async), would be served directly from the server using regular page refreshes...

Help!

jlmakes
  • 2,945
  • 1
  • 26
  • 38
  • 1
    Now that I have the answer, I found a duplicate question: http://stackoverflow.com/questions/11580004/angular-js-link-behaviour-disable-deep-linking-for-specific-urls – jlmakes May 03 '13 at 13:58

1 Answers1

18

Two options:

  1. If you're using <a /> tags, specify target="_self" to let AngularJS know it shouldn't capture their clicks (those links will be handled by browser normally). This is not a hack; this is normal documented behavior.
  2. Use $window.location = 'foo' as you have been doing. That is acceptable.
Ezekiel Victor
  • 3,877
  • 1
  • 27
  • 28
  • 4
    +1 for option 1, that fixes the back button in webkit with `html5Mode = true`; I definitely missed that in the documentation, thanks Ezekiel! – jlmakes May 03 '13 at 13:57
  • Victor's solution works. Setting target="_self" forces a page reload than just routing. – Mr. Doomsbuster Sep 15 '13 at 21:50
  • Thanks! You definitely save my life! – Tom Chen Jan 16 '14 at 14:31
  • 2
    Having to alter every single link on the rest of the site, including links that may be in content in the database, does not seem like an acceptable solution - there's got to be a better way! – shacker Jun 28 '14 at 01:07