After struggling a while with some code I am working on I figured out that depending on certain parameters, lets say user-role, or enabled-disabled menu item, navigation has to be allowed or forbidden. Angular's own router has solved this in a good way: Guards, nicely documented and full of copy-pastable StackOverflow examples everywhere.
Sad story for me, when I decided to start coding I said "I'll use Angular UI Router, it's easier to use" Ehm…. sort of…. I had some past experience with Angular UI Router and AngularJS. The Angular version is more than a little different, so it was quite a challenge to solve this.
Angular UI Router's tutorials are pretty clear on how to start, and on how to define routes so I'm not going to go further on that. About the navigation guards the Sample App includes some brief references, but they are still not completly clear for the casual developer (take a look at the code, if you are using Angular UI Router this is a MUST).
The Auth Hook
The main parts to understand are:
- Lines 14 to 16 where you can see the hook is applied only on states with the data attribute requiresAuth
- redirectLogin function (lines 20 to 26) where the transition object is used to recover the AuthService, and if the isAuthenticated condition is not met then navigate to the login page; else continue.
- Line 29, as the comments say Register the "requires auth"hook with the TransitionService. This is done before navigating to a new route (onBefore).
on the apps.module.ts files the import section includes all APP_STATES:
State definition on the Sample App gets a little complex (see files app.states.ts and contact.states.ts), so I'll simplify thing a bit (not saying this is the right way of doing things, just to understand them).
The requireAuthHook requires that each state has the requiresAuth attribute in the data section. So a valid route could be:
- data section lines 4 to 7
- line 5 has the requiresAuth attribute on true. My app also needed a routeEnabled checking which I'm going to explain later.
In a hardcoded-kids, don't do this at home version I had to deploy, I had to disable some links. Because my struggle was understanding Angular UI Router's hooks and making things work I didn't add a new hook. I added some new code so the redirectToLogin function ended like this:
Again this is not the right way, and sadly my real world path and requirements will probably lead to a poorly POC coded app.
The else section has all the magic, no rocket science in lines 6 to 15, get target destination, check if enabled, if disabled do nothing.
But everything is useless if you don't include the hooks in the code. So you'll have to include them.
So there's where you have to add the hooks.
In a "near" final version I ended separating the AuthHook and the EnabledHook. Sorry, but the code is too simple to include it in this article and enhance your copy-pasting skill level.
Using Angular UI Router with transitions hooks is a bit confusing, I know, learned after headbanging against the keyboard a few hours.
Simpler than Angular's router? Ehm… perhaps. There're some things I do prefer, such as the named views management, but (MHO) I don't particularly love Angular UI Router's documentation, and I feel there's a certain lack of non-biased examples. Anyway, all UI Router's code on Github is a good read if you pretend to use this routing library in any webapp.
I hope this posts helps someone, the same way it helped me when writing it.