Search code examples
angularjsangularjs-routing

Can AngularJS routing be used for some URLs and regular GET requests used for others?


I work on an ASP.NET MVC app which originally used traditional navigation (HTTP GETs and POSTs) and no AJAX/Fetch functionality. Over time, we have brought in AngularJS to take advantage of two-way binding and other UI improvements, but each page is still its own independent app/module. That is, we don't use AngularJS routing, but instead, when a page loads, it's a traditional GET request. This means angular.js loads and bootstraps each time, with the page itself being an isolated module and controller.

We'd like to start using AngularJS's routing to make certain sections of our app act as SPAs, with the eventual goal of making the entire site one SPA routed with AngularJS. With the size of the app and our small team, it isn't feasible to do it all at once, so we would need to do it gradually.

Is it possible to have certain URLs use AngularJS's routing, but have others do a complete page load (GET)? For example:

+------------------------------+-------------------------------+-------------------+
|         Current URL          |      URL to navigate to       |  Navigation type  |
+------------------------------+-------------------------------+-------------------+
| site.com/employee/edit/42    | site.com/employee/contacts/42 | AngularJS routing |
| site.com/employee/edit/42    | site.com/branch/settings/123  | Traditional GET   |
| site.com/branch/settings/123 | site.com/employee/edit/42     | Traditional GET   |
+------------------------------+-------------------------------+-------------------+

Pages within the same "section" of the software (in this case, /employee/*) would be part of the same AngularJS module, and navigating both to and from a page within that module would use AngularJS routing. All other navigation would fall back on regular GET requests.


Solution

  • The answer to this question is yes.

    I would first recommend utilizing the ui-router project for all of your routing. Their documentation is quite good and the Angular team recommends this over their own router.

    The default routing mode of this library utilizes document fragments to navigate so if you were to host your AngularJS site at say site.com/employee/spa/index.html you could then manage all of your routes using the ui-router library via document fragments.

    So you would see something like

    site.com/employee/spa/#!/contacts/42
    site.com/employee/spa/#!/contacts/3000
    site.com/employee/spa/#!/contacts/42/detail
    

    etc...

    If you were to directly request one of these urls, whatever webserver you are using would not see these document fragments, only site.com/employee/spa. Once the page renders ui-router will handle routing / data resolving.

    There are reasons you may not want to use document fragments. An example of this would be integrating with a single sign on oAuth service. When redirected back to your site they also will not be able to utilize document fragments so you will always have to accept their requests at your root location.

    For this you can switch to html5mode: https://docs.angularjs.org/api/ng/provider/$locationProvider#html5Mode

    In this mode the document fragment will be gone. This means however your webserver will see all of the full url requests as instead of

    site.com/employee/spa/#!/contacts/3000
    

    They will be sending

    site.com/employee/spa/contacts/3000
    

    You can configure rules within your webserver that redirect all requests to anything after site.com/spa/employee to go site.com/employee/spa/index.html to get around this. This depends on the webserver you use though.

    I'd personally stick with the default unless you absolutely need to use html5mode.

    EDIT: Added an SPA path to your spa routes, I didn't realize you specified two employee routes. You should definitely have something prepending employee specifying that a certain portion is SPA specific.

    EDIT EDIT: You could slowly migrate your other employee route over to spa and start doing the same for your other routes, eventually everything can be migrated to an /spa/ root and you can remove the need for it altogether.