Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I mix links that trigger page refreshes, with Angular's html5Mode = true without breaking the back button?

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!

like image 969
jlmakes Avatar asked May 02 '13 11:05

jlmakes


1 Answers

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.
like image 54
Ezekiel Victor Avatar answered Nov 02 '22 06:11

Ezekiel Victor