5

Changing routes via ui-sref works correctly.

When I refresh the page manually on the base url (example.com/account), everything similarly works.

However, when I refresh the page manually and the url contains a hashbang (i.e. http://example.com/account/#/billing, I see the following error in the console.

TypeError: Cannot read property 'charAt' of undefined
at Object.$$parse (https://ajax.googleapis.com/ajax/libs/angularjs/1.2.25/angular.js:9321:40)
at https://ajax.googleapis.com/ajax/libs/angularjs/1.2.25/angular.js:9878:21
at Scope.$get.Scope.$eval (https://ajax.googleapis.com/ajax/libs/angularjs/1.2.25/angular.js:12701:28)
at Scope.$get.Scope.$digest (https://ajax.googleapis.com/ajax/libs/angularjs/1.2.25/angular.js:12513:31)
at Scope.$get.Scope.$apply (https://ajax.googleapis.com/ajax/libs/angularjs/1.2.25/angular.js:12805:24)
at done (https://ajax.googleapis.com/ajax/libs/angularjs/1.2.25/angular.js:8378:45)
at completeRequest (https://ajax.googleapis.com/ajax/libs/angularjs/1.2.25/angular.js:8592:7)
at XMLHttpRequest.xhr.onreadystatechange (https://ajax.googleapis.com/ajax/libs/angularjs/1.2.25/angular.js:8531:11)

After reading about this error and adding breakpoints, I noticed that, on load, the path is being temporarily rewritten from forms like

/account/#/billing
/account/#settings

where account is the base for the app, to forms like

/billing/ 
/settings/

Eventually, after the error occurs, the correct url forms are restored in the address bar.

These temporary (intermediate) paths seem to cause the following code in $$parse to break. AppBase is bound to "example.com/account/" and url is bound to values like "mysite.com/billing". withoutBaseUrl is bound to undefined since the url does not contain characters extending beyond appBase.

  this.$$parse = function(url) {
    var withoutBaseUrl = beginsWith(appBase, url) || beginsWith(appBaseNoFile, url);
    var withoutHashUrl = withoutBaseUrl.charAt(0) == '#'
        ? beginsWith(hashPrefix, withoutBaseUrl)
        : (this.$$html5)
          ? withoutBaseUrl
          : '';

Here is my relevant code:

 plaidApp.config(['$stateProvider', '$urlRouterProvider',
'$interpolateProvider', function($stateProvider,
  $urlRouterProvider, $interpolateProvider) {

$stateProvider
  .state('account', {
    url: '/',
    controller: 'MainCtrl',
    templateUrl: 'dashboard_home.html',
  });

$stateProvider
  .state('metrics', {
    url: '/metrics',
    controller: 'MetricsCtrl',
    templateUrl: 'dashboard_metrics.html',
    resolve: {
      actions: ['actionModel', function(actionModel) {
        return actionModel.fetch();
      }]
    }
  });

$stateProvider
  .state('billing', {
    url: '/billing',
    controller: 'BillsCtrl',
    templateUrl: 'dashboard_billing.html',
    resolve: {
      bills: ['billingModel', function(billingModel) {
        return billingModel.fetch();
      }]
    }
  });

$stateProvider
  .state('resources', {
    url: '/resources',
    controller: 'MainCtrl',
    templateUrl: 'dashboard_resources.html',
  });

$stateProvider
  .state('settings', {
    url: '/settings',
    controller: 'SettingsCtrl',
    templateUrl: 'dashboard_settings.html',
  });

$urlRouterProvider.otherwise('/#');
$interpolateProvider.startSymbol('{[{').endSymbol('}]}');

}]);

6
  • 1
    if account is the base for the app, shouldn't your child state be account.billing and a URL of account/billing?. Commented Dec 17, 2014 at 22:31
  • I don't explicitly set a base anywhere (not sure if I should). I just meant that the backend server renders the angular app at /account/ Commented Dec 17, 2014 at 23:06
  • are you using HTML5 mode? Commented Dec 26, 2014 at 9:13
  • What happens when you change $urlRouterProvider.otherwise('/#'); to $urlRouterProvider.otherwise('/'); ? Commented Dec 29, 2014 at 6:14
  • What version of angular? Commented Dec 30, 2014 at 19:37

3 Answers 3

2

Try writing the interpolate statement before the routes are defined:

$interpolateProvider.startSymbol('{[{').endSymbol('}]}');

$stateProvider
 .state('account', {
 ...

The template linking and compiling might have started before the interpolate statement is executed and in that template if you have used '{[}', it might not be able to parse it.

Sign up to request clarification or add additional context in comments.

1 Comment

This didn't affect it, unfortunately. I should make that change, though, regardless. Thanks.
0

The $urlRouterProvider.otherwise() should point to the url of your default state in this case its the account state:

$urlRouterProvider.otherwise('/')

Comments

0

I finally solved this ( I think). Looks like it's a dependency issue. Once I removed HistoryJS (1.8.0), everything worked as expected.

  <script src="/bower_components/history/scripts/bundled/html4+html5/native.history.js" type="text/javascript"></script>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.