I have a, hopefully, simple question. I've built a small App with Ionic and AngularJS. There are two States, one of them is a tab containing a form. When submitted the form tab shouldn't be accessible anymore. I've tried to write a boolean variable in local storage and it works fine for me. Unfortunately when I submit the form I can still push the back button of ionic or the android hardwarebutton to go back to the form and submit again. I called a function via ng-init that switches the state before loading but this only works with refreshing the page, not at the state change.
How can I listen to a state change? Do you have a better solution?
It's quite easy actually, UI-router give you access to 3 differents state listener :
$rootScope.$on('$stateChangeStart',myFunc) -> fires when state is changing
$rootScope.$on('$stateChangeSuccess', myFunc) -> fires when state has changed successfully
$rootScope.$on('$stateChangeError', myFunc) -> fires when state change has failed
Then you can disallow the access to one page using the resolve attribute of your state by associating it to a promise. see doc
If the promise is resolved, access is granted else access is denied.
Related
I am working on an angular web application where I want to show the user messages about different actions (like success, failure, etc.). These messages are set to clear automatically after 10 seconds, or when the user clicks the x button beside every alert. This is the easy part.
The difficult part is - I want to maintain these messages when the user navigates to different parts of the application. Something like facebook/google chat boxes.
I initially went through some ideas and decided on a solution where I stored the messages in an array in the local storage and every web page had code to look for these messages and display them if found.
But, I faced issues with the timing of the messages disappearing automatically (the timer reset to 10 seconds for all messages on page load). And also whenever the URL changed, the messages would go away and would load as new alerts after the new web page finished loading.
What is the correct way of doing this?
Whenever an alert appears in your application, you can store its timestamp together with the message. And on the page load call setTimeout for each alert with a callback of removing this message and the time difference between now and the timestamp+10sec.
Using your implementation, the timeout issue is easy to fix: when you store the alert, include an epiresAfter property as well. This property would be a timestamp af when you expect the the alert to no longer display.
Then you set up a timeout that either:
polls and checks the timeout, clearing it if the current time is past the expiration time
or a timeout that triggers after the difference between the expiration time and the current time.
I would consider treating your Message component as a singleton, i.e. it only ever has one instance. If the Message component is a child to other components, then it will be removed when it's parent component is removed from the DOM.
Consider moving your messages component to the root/app level (i.e. inside your AppComponent). This way as the user navigates around your app, the Messages component will always be visible. Further, the state of the notifications can be stored within this Messages component, so it's own timer wouldn't be affected by the rendering/removal of other components.
This all assumes you aren't using some sort of global store for your app state. If you are, consider Hyun Woo Krassilchikoff's answer which details implementing a global NGRX store.
The most efficient way is actually to use an NGRX store for your error message and a unique component in the main layout of your application rendering any message streamed from the store.
You'd need:
an action for pushing any kind of alert:. E.g. PushAlert
an action for clearing the alert. E.g ClearAlert
a reducer for managing both actions above
a selector to stream the portion of the state related the alerts
an effect which triggers ClearAlert 10 sec after detecting PushAlert
a component which displays the alert streamed by the store
After a successful http request i need to reload the page to update the view outside the ng-view so i am using $window.location.reload().This is working fine but the problem is i want to reload the page silently without notifying user as the page transition works in angularjs.I also used $route.reload() but this did not work in this case.So is there any way in angularjs to reload the page in background so that the user is unaware about the reload ?
$scope.save=function()
{
$window.location.reload();
}
when the http request is resolved just run the method that loads the view again (passing the new data)
You can use events in Angular Js for updating portion outside of the ng-view. Like emit event when http request done & then broadcast it it or listen as per your requirement.
I would prefer storing user details in $localStorage, so that it would be stored until cache is cleared. It comes very handy to store information such as user details in the client side and it can be accessed across all controllers. $localStorage service can be injected into any controller and values can be set. Resetting is also easy($localStorage.$reset()) to clearing information when required. You could also use $sessionStorage.
You solve this with using $rootscope, set username with $rootScope variable,
you will update that $rootScope value when you get new username in httpservice
Edit
If in your side menu username value in text like below:
<div id="elementId">UserName</div>
or
<span id="elementId">UserName</span>
then
assign new user name value to userNameValue variable and do like below:
Use Jquery $('#elementId').text(userNameValue)
What I want: if the user reloads the page with his redirect to another page.
(Only when updating the page)
Example:
I'm on main/bla and reload the page and I'm redirected to the main/
window.onbeforeunload = function(e) {
$state.go('main');
};
Does not work for me.
There is a lot happening when you want to change states.
For one, it could trigger extra network activities such as resource download. There isn't enough time for angular to change states, change URL and go through the lifecycle of navigating routes.
some options:
Do the redirect after the refresh happens (save something in localstorage, cookies, ..)
Redirect manually, update document.location or similar
Check once if you are using proper injector in js controller or is there any other error on console.
Check for:
you have given proper state name $state.go('main'),it should defined in routing.
Should use injector $state in controller.
I am using angular factory to pass data from one form to another form.
Working fine, but when I refresh the page, data lost from the page.
How I can resolve this ?
I am using below code
angular.module('app')
.factory('SignupService',function() {
return {
first_name : ''
};
} );
and I am assigning value like this in form1.
SignupService.first_name = $scope.first_name ;
And getting value in form2 like this
function Signup2Ctrl($scope,$http,$location,$auth,$state, SignupService){
alert(SignupService.first_name);
});
How to resolve this or any other alternative to handle this.
Thanks in advance.
AngularJS is used to build single-page web applications (SPA). When you reload the page, the application goes into its initial state. If you want to preserve any data, you should use browser cookies, local storage, cache etc.
The whole idea of AngualrJS is not to reload the page. That what makes it more suitable for developing native apps where the user doesn't have the option to relaod the page in the way a browser provides.
There is a way to prevent the code from resetting when a user hits refresh. You would nee to implement something like this:
var windowElement = angular.element($window);
windowElement.on('beforeunload', function (event) {
// do whatever you want in here before the page unloads.
// the following line of code will prevent reload or navigating away.
event.preventDefault();
});
To use it, simply create a .run instance and implement it there. Have you read about the loading order of an AngularJS app? Read more about it here: AngularJS app.run() documentation?
You should also look into $routeprovider: https://docs.angularjs.org/api/ngRoute/provider/$routeProvider
If reloading is a necessary part of your app, maybe you could create some kind of reload button if using the ngRoute module?
I am building SPA application is emberjs framework and I need to ensure that the application instance is running only once (on single tab) on same domain.
Analogy of mutex to prevent multiple instances known from desktop application development world.
There are some solution I am considering just now like using localStorage locks or window.postMessage or SharedWorker but non of them looks bulletproof to me.
Do you have some ideas?
Thanks is advance.
I've used localStorage to make sure when users log out in one tab it logs them out in other tabs and it's worked quite well.
Bind to the storage event on the window object and use the event.key/event.newValue keys to determine what action to take. You can also use the event.url key to make sure the storage event is firing from the correct page. In my code I set a logged-out flag if the url, key and newValue data validates.
Bind to the focus event on the window object and check the value of the logged-out flag and auto-logout the user if it's set to true.
For my purpose I had to initialize the localStorage data to "not logged out" on page load because the storage event will not fire if you don't actually change the value of the localStorage key you're watching. I.e. if the value is blah and you set it to blah, no event will fire.
This works back to IE 8 too.
For your purpose you could set a localStorage key/value when someone logs in and block the page from working if that key/value is already set. Maybe set a timestamp as the value so if someone doesn't properly logout they can get back in after so many seconds. Then set an interval to update the timestamp while the user is logged in.
This is untested, if you go down this road I'd be interested to see how it works for you and what you had to do to make it work.