I have a site with a main state and view that can contain a number of sub views for each route. I'm implementing authentication and I'm using the $stateChangedStart event to check whether a user should be able to see the page. If the user is not permitted to view the page, I still want them to be redirected, but I want to change the main view to a forbidden view.
In the $stateChangeStart event I have access to the "toState" object which I can then modify the views of. Unfortunately, this doesn't seem to have any effect.
Here's a plunker to explain: http://plnkr.co/edit/7pvIEQ6e4zitp6ANJJ9h?p=preview
I've realised that I'm thinking about this the wrong way. I don't need to intercept the state change event because I'm awlays going to state change to that page anyway. What I need to do is handle the permissions issue on the page itself.
Related
I have a problem with blocking page changes in the application. The application is written in react and installed in liferay (CMS). It wants to keep the user on the payment intermediary selection screen. Unfortunately, the methods I know do not work properly. Blocking on the "beforeunload" event only blocks the closing of the page or its refresh (I'm only interested in closing the tab, but it is an additional condition). Blocking the website by react router doesn't work properly either. The prompt component works only within the scope of the added page, and no longer works in the navigation created on liferay. This is the same for useHistory (history.block('msg')), because it works just like the prompt component. I also tried to get this effect with other events, unfortunately to no avail. Does anyone have an idea to solve this problem? Thank you in advance.
I'm not aware about Liferay navigation behavior but I can see two resolutions:
you could go on using react router to block the transition to another route:
You could find a full example on the official docs (https://reactrouter.com/web/example/preventing-transitions).
<Prompt
when={isBlocking}
message={location =>
`Are you sure you want to go to ${location.pathname}`
}
/>
if there are parts of your application not handled by react-router you could rely on some event from history, like the one described here:
https://developer.mozilla.org/en-US/docs/Web/API/WindowEventHandlers/onpopstate
A popstate event is dispatched to the window each time the active history entry changes between two history entries for the same document.
I have some routes within my application. There are some UI changes within a same route. For example, when I click a button, I get resources from the server and display it as a list. I want to mark this point as a separate browser history, so that when the user clicks back from any next route, I am taken back directly to the list instead of the button.
For example,
Route -A > Button is displayed
Upon click,
Route A -> List is displayed
Now when item is clicked
Route B -> Item is displayed.
Now if I click back from Route B, I want to be taken back to Route A with list instead of the button. How can I achieve this?
Any ideas?
I'll assume your app is an SPA (single page application). Routing is then just another way of maintaining application state. Therefore I see two common ways to resolve this:
Create another sub-route for showing list
Implement custom state management. In this case, when you go back to your route you would restore state. Many people will use Redux for global state management, but you are free to set up your own infrastructure.
Either way, you need a way to tell your view that it should render with a state different than the default.
I hope that helps.
I have simple app and one view that is about to change via navigation bar.
Default angular's behaviour is to call controller code every time I am navigating. This arise problem of saving state when changing views (i.e calendar state, checkboxes etc.)
I search for most common well known solution, that is why I am asking below questions:
Should I encapsulate state data in service and load every time controller is called? And this is fine?
Should I prevent situation of calling controller every time I am switching to different menu view?
Does angular-route handle for me preventing of calling controller every time view changed.
Does ui-router handle same as pt. 3?
Single page apps require careful management of events, DOM elements, and javascript objects in order to avoid leaks.
We're going to manage memory and squash leaks as best we can. That said, the application is large, uses many libraries, and could be left open for days at a time.
We need a safety valve.
I'm looking for ideas on how to unobtrusively trigger a page refresh in a single page app as a way to force the release of memory.
One idea is to detect when the user is idle for more than N minutes and do a refresh then, because it's unlikely to interrupt them. Much of the application state is saved in the URL using AngularJS ui-router, so this will work some of the time.
The problem is that while some state is in the router, not all of it will be. The user could have unsaved changes, or have some modal or flyout menu open which isn't in URL state. A solution could be to detect user changes and ban a refresh if any changes have taken place that aren't in the url. I don't see how to implement this generically though. Maybe we just put everything that's even a little bit important into URL state.
Another idea is to watch the application state change event $stateChangeStart and, every Nth time, do an actual browser navigation to that URL instead of just an app state change. This will never result in lost "sub-state", but will cause a slower page change response and a screen flicker. Maybe every 20 screen changes this is OK though.
Does anybody have any better ideas?
Just an idea on unsaved changes and data:
I have an a single page app that in one section has several tabs each containing a form. When each form becomes "dirty" it triggers a notification to the Main Controller, and sets a flag for that form. When a user saves a particular form the flag becomes unset. If the user tries to navigate away - before the route change occurs, it checks to see if any of the flags are set and then notifies the user via a modal that some particular information hasn't be saved. The user can then decide whether to continue with the route change or go back and save the data.
This could easily be modified to perform the same check on page refresh and if there is unsaved data either cancel the page refresh or save the changes to the browser's local storage for recall after the page has finished refreshing.
This is a problem I've seen discussed in a few posts around Stack, but I haven't found a clear answer that actually works for me. I expect this to be a common problem, so alternate approaches would be fine too.
Basic concept is that I wish to conditionally display one of two states when a user visits the site. I have an API call to my external server to check if the user's session is active. If so, I can route to the 'home' page, otherwise I route to the 'welcome' page.
The problem is that I don't know how to achieve this.
My initial idea was to create a resolve object in the home state, and resolve the api.isLoggedIn call there first. That would stall the transition so that I could check the state $stateChangeStart event, and then call event.preventDefault if necessary.
The problem with this is that onStateChangeStart is called before the resolve method, so I cannot know whether the user is logged in before the state change.
At the moment I'm thinking that the only way I can achieve this is by presenting an initial state whose controller will check if the user is logged in and then manually call a state change based on the response.
Is there a more idiomatic solution?