Introduction
In this blog, we’ll give you a rundown of how we’ve implemented routing in our single page project management tool – PineStem.
Routing is a process of navigating the user to the desired location based on the action they perform.
Maintaining the user’s navigation history is a major challenge while developing a single page application(SPA).
To overcome this problem, we implemented a simple stack based solution which only involves pushing and popping an object with required properties.
Maintaining the user’s navigation history is a major challenge while developing a single page application(SPA).
To overcome this problem, we implemented a simple stack based solution which only involves pushing and popping an object with required properties.
Demo
You can find the sample code and a demonstration in the Plunker here – https://plnkr.co/OnBe1bc9Q7h1tYBK1pSY?p=info
Implementation
For PineStem, we’ve used a popular routing plugin named AngularUI Router.The idea behind our implementation is quite simple. We store the parameters that are required to navigate back to a particular state in an object and push it into an array.
AngularUI Router provides us an event called
$stateChangeSuccess
, which gets triggered on every successful state change. We store the information that is needed to navigate to that particular state on this event, which includes the stateParams, URL, a template that has to be loaded and name of the state. Whenever a user tries to go back by clicking on exit/cancel button or browser’s back button, we pop out the latest element in the array and use that for the state change. This way, we can maintain a stack to hold the user navigation history accurately.
A typical object that we store on each state change could be the one that is shown below –
In PineStem, we have two ways of navigation. One is through the main window and another way is through the sidebar that is present on the left side.
Screenshot of the application is shown below.
In order to identify the mode of user’s navigation, we used two flags –
Using the above-mentioned flags, we track user’s way of navigation and perform the necessary action.
- When a user traverses through the main window, we maintain their navigation history by pushing the state information into the array.
- If the user tries to navigate through the sidebar (
isFromNavBar
istrue
) then we clear the route history. - If the user clicks on the exit/cancel (
isCancelOrSave
istrue
) button of any entity, then we pop out the last element in the routeHistory and redirect user to the previously visited state. To know more aboutisCancelOrSave
flag, please visit Handling back or exit button.
Logic breakdown
Let us see the actual logic in detail –
Following are the steps that take place when a user tries to navigate around three modules namely module_one, module_two, and module_three.
Step 1 – Assume an empty array. Eg:
$routeHistory = [ ];
Step 2 – Now when the user tries to open module_one, there is no need to perform any action as this is their first step.
Step 3 – From module_one user opens module_two. Then we push an object (with details as discussed above) into the array. Thus,
$routeHistory = [module_one_route]
Step 4 – Then, from module_two user tries to go to the module_three. Now, we will push the object related to module_two into the array. So, our array becomes
$routeHistory = [module_one_route, module_two_route]
Step 5 – Let’s say the user clicks on exit/browser’s back button in the module_three. Then we need to check the
$routeHistory
variable and if it is not empty, the latest entry is popped out. We use this object to render the last state.Handling the back or exit button
We can find exit/cancel button in various sections of the application. On clicking this button, the user gets redirected to the previously visited state. As expected
$stateChangeSuccess
event triggers, and we save the last state visited by the user. Navigation by browser’s back button also triggers $stateChangeSuccess
event.
Saving the state on the back/exit leads to a continuous loop.
Consider an example – Assume there are three pages named A, B, and C.
- User visits a page named page A. From page A, user visits page B, then from page B to page C. By now, the stack is filled with [pageA, pageB].
- Then, he/she tries to go back by clicking on the browser’s back button. As expected, they are redirected to page B using the latest entry of the stack.
- Along with the redirection, page C is saved on successful state change which makes the contents of the stack – [pageA, pageC].
- Then, if the user tries to click on the back button again expecting to be in page A, instead they will get redirected to page C. This happens because page C is the latest element in the stack.
The same is illustrated in the image below.
In order to skip the saving of the last state, we set the flag
isCancelOrSave
to true
. Whenever a user clicks on the exit/cancel button or the browser’s back button, isCancelOrSave
state is set to true
.
Then on the
$stateChangeSuccess
event, the following code snippet is executed.
Setting the
isCancelOrSave
manually when the user presses the back or exit button is simple enough, but doing so on the browser’s back button click needs another small snippet of code to be added in the $stateChangeSuccess
event.Browser compatibility
The
window.event
property is available in Google Chrome and Edge only. So, the above-mentioned solution is applicable only for Chrome and Edge.Different scenarios
Let us see a few scenarios that we handled using the above implementation.
Case 1
Above mentioned steps are illustrated through an image
No comments:
Post a Comment