Last Updated: February 25, 2016
· kingsleyadio

Some Angular UI Router gotchas and how to deal with them

I would be discussing 2 pits that you might fall into when using angularjs with UI router, and how you can pull yourself back up, or better still, avoid the pit altogether in the first place.
This text is meant for developers writing/intending to write single page apps, but can of course be applied in other scenarios as well

Dealing with authentication upon hitting your app's URL on the browser

You might probably have had your fair share of headache figuring out how to properly deal with this problem. Take a look at this scenario: User hits the URL, you want to check if he already has an auth token, and probably verify that the token is still valid before rendering the page they requested. Of course, at that point, your app is still very much stateless, so state tracking is impossible. And things might even get worse if your app has several states sharing the same URL (we'll get back to that shortly) <br/>
In my case, this is what I tried: change the location hash to a temporary one, render a wait screen, verify the token, setup a stateChangeStart listener and redirect back to the initial location that was requested. The stateChangeStart here helps to properly handle routes with privileged access. Unfortunately, manipulating the location hash this way resulted in an infinite loop (I'll spare the details). It was however a result of the non existent temp. location, url router's otherwise trigger and the stateChangeStart listener itself. <br/>
Okay, the fix was to reroute to a temp. state instead (with the state now mapped to the temp. location) and wrap the stateChangeStart listener in a $timeout function. This has 2 advantages: whatever URL the state has is now existent (avoiding the otherwise trigger), and using the $timeout ensures that all verification processes actually completed before listening to state change starts, consequently solving the auth problem and simultaneously avoiding the loop as well.

Dealing with multiple states with the same URL

You would probably have considered this for an app where some users have more permission than others, e.g a URL for page owners and page viewers, whilst having the same URL should however provide different set of functions, render different views, etc. You would agree that ordinary CSS manipulation will not handle all the cases. <br/>
Anyway, this is simple: routing to that URL always trigger the first state eventually, making the second state inaccessible whatsoever. You could be very clever, and explicitly perform a $state.go to the second state, but these would happen: (state activates, location updates) in that order. Now upon location update, the state is again returned to the first. Sad! <br/>
The fix was to $state.go to the first state instead, resolve the access level of the user and send him to the second state (if he has enough privilege). Making use of the resolve here ensures that the appropriate view is determined before actually rendering it. The catch is that elevation is always a better choice to relegation! :)

2 Responses
Add your response

On dealing with multiple states with the same URL, will it work to create an abstract state, resolve in that state, then redirect to the child states accordingly.

over 1 year ago ·

@fathermerry yes, it works. I'm actually doing that myself :)

over 1 year ago ·