20

This is my first experience with AngularUI Router, so I guess I'm making a newbie error and hope somebody can guide me.

I've configured a single-page application to use Angular UI Router in HTML5 mode and it all seems to work as expected.

.config([
    "$stateProvider", "$urlRouterProvider", "$locationProvider",
    function ($stateProvider, $urlRouterProvider, $locationProvider) {
        $stateProvider.state("concept", {
            url: "/concepts/:conceptKey",
            templateUrl: "/templates/concept-view.html",
            controller: "conceptViewController",
            resolve: {
                concept: [
                    "$stateParams", "conceptsApi",
                    function ($stateParams, conceptsApi) {
                        return conceptsApi.getConcept($stateParams.conceptKey);
                    }
                ]
            }
        });

        $urlRouterProvider.otherwise("/");

        $locationProvider.html5Mode(true);
    }
])

However, the same page also contains some links to other static pages on the same site, using relative URLs. Prior to installing Angular routing, these links worked correctly, but now they are broken. Specifically, clicking any one of these links correctly changes the browser address bar, but does not trigger navigation to that destination page.

I assume I need to add something to tell the routing configuration to ignore certain URL patterns, but I haven't found any information that shows me how to do this. Any suggestions please?

Thanks, Tim

Tim Coulter
  • 8,705
  • 11
  • 64
  • 95
  • It seems like your server side is not well configured. Anyhow, check [this link with example/plunker](http://stackoverflow.com/a/26009350/1679310) of UI-Router and html5. If the server is configured well - this should work as well. – Radim Köhler Jan 24 '15 at 17:30
  • Thanks for your suggestion, but I don't see how this applies to my situation. UI routing is working correctly for URLs that correspond to the defined state configuration, but it prevents navigation to a static page on the same domain. If I request that static page directly from a new browser tab, it renders correctly, and equally if I disable routing. The problem only occurs when routing is active, wherein all links within the SPA that target pages outside the SPA are broken. – Tim Coulter Jan 24 '15 at 18:05
  • I guess I see now. Then (If I do understand your issue) I would say, that you just have to change your server part. I am using ASP.NET MVC ... and that's a place where I can set how the SERVER reacts on any url. Some are redirect to index.html... some are served as expected. Check it there... (link how to set that in mvc http://stackoverflow.com/a/27707238/1679310) – Radim Köhler Jan 24 '15 at 18:06
  • I am also using ASP.NET MVC and I have created a controller action that is mapped to respond to every possible URL used by the UI routing scheme. It always delivers the same response, regardless of the URL and it relies on the client to interpret the URL and make API calls to populate the view. If I issue a request to this controller action, it always responds as expected (verified using Fiddler). So, the problem seems to me to be client-side. UI routing seems to be preventing the browser from following normal (non-routed) URLs as I would expect it to. – Tim Coulter Jan 24 '15 at 18:19

1 Answers1

39

After some investigation I discovered that this issue is not specifically related to Angular UI Router. The same behavior is also present in the native AngularJS routing mechanism and is caused by the link rewriting logic implemented by $location, as described in this documentation.

Further discussion of the problem is here.

I found two possible solutions, both of which seem to work well:

Explicitly target links to static pages: By including the attribute target="_self" in any links to static pages (i.e. pages that fall outside the defined Angular routing scheme) they will be ignored by AngularJS and thus rendered correctly.

Disable link re-writing: When configuring Angular routing in HTML5 mode, two syntax formats are supported. The simplest format ...

$locationProvider.html5Mode(true);

... enables HTML5 mode with the default configuration. However, the long-form syntax provides access to additional configuration properties, one of which solves the above problem by disabling Angular's default behavior of intercepting and re-writing link URLs:

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

I used the 2nd solution and it appears to have no adverse effect on the behavior of URLs defined in the routing scheme. This solution appears to work equally well with Angular UI Router and with native AngularJS routing.

Tim Coulter
  • 8,705
  • 11
  • 64
  • 95
  • Using the first option you have to add to all of your links "target="_self" but you have the option to choose if a link will change the url or it will redirect to this url... the second one.... doesn't need to change all your links... but you can't choose the 2 different types of links.... right?? – Michalis Sep 21 '15 at 10:50
  • @Michalis Yes, the first approach offers finer-grained control over the behavior of links, but is more onerous to implement. The second approach implements the same behavior globally, but does not allow the flexibility of individually configuring link behavior. – Tim Coulter Sep 29 '15 at 07:21
  • 1
    Two more solutions from the `$location` documentation - Angular will also not rewrite the url if it's an absolute url that goes to another domain or if the url starts with "/" and leads to a different base path. – adam0101 Oct 26 '17 at 19:59