7

trying to set the correct base href value for an angularjs html5 web app to work in cordova

initially using $locationProvider.html5Mode(true) with <base href="/">:

  • app works perfectly in a normal browser
  • cordova gives resource errors for css / js / templates etc
    (I believe it looks for resources within the cordova root directory rather than the platform root?)

Tried a few alternatives are floated around here on SO and ui-router FAQs:

<base href="."> with html5 mode as per this answer :

  • assets are found ok in cordova (no resource errors)
  • ui-router goes into a tail-spin with infinite loop and the following error message
    Error: Failed to execute 'pushState' on 'History': A history state object with URL 'https://page/' cannot be created in a document with origin https://example.com

<base href="./"> with html5 mode:

  • assets found in cordova (no resource errors)
  • gives me the dreaded Error: 10 $digest() iterations reached. Aborting! message tried using frankwallis solution mentioned here but that didn't help (same error)

no base href with $locationProvider.html5Mode({enabled: true, requireBase: false});

  • assets found in cordova (no resource errors)
  • pages start loading inside themselves ?? ...like angular bootstraps twice in some states ?

my app config definition looks like:

myApp.config(['$locationProvider', '$urlRouterProvider', '$stateProvider', '$stickyStateProvider', function($locationProvider, $urlRouterProvider, $stateProvider, $stickyStateProvider) {

    $locationProvider.html5Mode(true);

    $stateProvider
    .state('root', {            // we define a 'root' state so that we can load some essential data prior to any template being loaded
        url: '',
        abstract: true,
        sticky: true,
        views: {
            'root': {
                template: '<ui-view/>',
            }
        }
    })
    .state('root.worldmap', {
        url : '/worldmap',
        templateUrl : 'templates/worldmap.tmpl.html'
    })
    .state('root.faq', {
        url : '/faq',
        templateUrl : 'templates/faq.tmpl.html'
    })
    .state("otherwise", {
        url: "*path",
        views: {
            'root': {
                template: "",
                controller: ['$injector', function($injector) {
                    var $state = $injector.get("$state");
                    $state.go('root.worldmap');
                }]
            }
        },
    });
    $stickyStateProvider.enableDebug(true);
}]);

For info: using this method of alternative cordova deviceready vs angular.element bootstrap for cordova / browser respectively

Community
  • 1
  • 1
goredwards
  • 2,486
  • 2
  • 30
  • 40

1 Answers1

5

OK so the way to get this working is by removing the base href AND disabling html5 mode :

  • [optional] create & checkout a new branch called dev-cordova or similar
    • this allows you to switch quickly between browser and device code
  • delete / comment the <base href="/"> in the main index.html
  • ensure that html5 mode is disabled in app.js by either

    $locationProvider.html5Mode({
        enabled: false,
        requireBase: false
    });
    

    or

    $locationProvider.html5Mode(false);
    

Don't forget to run cordova build ios (after you grunt / gulp etc to compile the js files)
...this ensures the files in the cordova /platforms/ios/www directory are updated.

goredwards
  • 2,486
  • 2
  • 30
  • 40