close/leave page event with AngularJS - angularjs

I am trying to implement a single page application that starts with a login form. For front-end I'm using AngularJS.
In the login's controller I check the authentication data, and if it is ok, I set a cookie (using $cookieStore service) with some user data and route to another view. Here, in the controller of the second view I check if the user from the cookie is empty and if yes, I redirect to the login view.
What I want to do is when the user close the browser, or if leaves the page the cookie to be removed.
I have tried to use:
$scope.$on("$locationChangeStart", function(){
$cookieStore.remove('user');
});
or
$scope.$on("$destroy", function(){
$cookieStore.remove('user');
});
but it does not work.
I want to avoid the scenario when a user log in (the cookie is set) and is redirected successfully to the second view, and after this close the browser/leaves the page (the cookie is still there). Another user write the url of the second view and because the cookie with the data of the first user is still there, he succeed to authenticate.
Can anyone help me with this?
plunker link

I am not sure. But maybe the browser closes before you even do anything in your logic.
Try this :
$scope.$on("$locationChangeStart", function(event){
event.preventDefault()
$cookieStore.remove('user');
});

try this code, it will works
$scope.$on('$locationChangeStart',function(event) {
if($scope.formsubmitted && $scope.myForm.$dirty){
var answer = confirm("Are you sure you want to leave this page?")
if (!answer) {
event.preventDefault();
}else{
$cookieStore.remove('user');
}
}
});

Related

AngularJS reloading multiple tab in the same time if any change

I have an add form that if the user file the form and submit, in the same time, user can see the data in the same page in table with ui-view and this is not an issue!!
Problem is: if i open more than one tab in the same browser, that post or change reflection doesn't show in other tab without refreshing or reloading. i want to see change in other tab of browser or other browser without reload
I want to see the change without refresh or reloading.
if i reload in other tab, it works but if i dont reload in other tab, the change doesn't effect
here you go for my post method:
$scope.formModel = {};
$scope.onSubmit = function () {
$http.post('http://127.0.0.1:8000/api/v1/contact/create/', $scope.formModel)
.then(function(response) { //if success, below fuction will execute
$scope.successPost = 'You have successfully submitted your Contact';
$timeout(function() {
$scope.successPost = '';
}, 4000);
//below $scope will push data in client site if the request is success
$scope.contacts.push(response.data);
//if any error occurs, below function will execute
}, function(response) {
// below variable will get predefined message that will explain exactly what happened
var errorData = response.data;
$scope.errorPost = Object.values(errorData)[0][0];
$timeout(function(){
$scope.errorPost = '';
}, 4000);
});
$scope.formModel = {}; //It means, after submit, the form field will clear
$scope.addContactForm.$setPristine();
};
I want to see the change in the other tab without refresh or reload
well browser tabs are per definition separated from each other and can't communicate directly between each other.
there are certain possibilities to handle that: for example you can have a separate external service and always poll that service for latest changes and if something changes automatically call reload.
or you could use a service that provide a websocket that sends you to the frontend an update notification once something changed in your data.
Just want to point you in the right direction, the topic is to big to provide a finished solution. I recommend to do some research on how to communicate between tabs / how to build a service with an update notification for new data
Edit: Just to add #Yftach point from the comments: Theoretically localstorage is shared between tabs, so theoretically you could have a variable there and watch in an interval for changes. However the solution with a separate server is (at least in my eyes) way better

ngstorage's $localStorage still available in angular after deleting browser data

I am using ngStorage for storing data in local storage. I am facing this weird issue where, when I am deleting the localstorage from the browser, my website's user doesn't get logged out on url change.
Here's the code that keeps the check whether the localstorage exists or not and then does the appropriate route:
$rootScope.$on('$locationChangeStart', function (event, next, current) {
//it always by passes this
if (!$localStorage.currentUser) {
$location.path('/login');
}
});
Only when I refresh the page, it automatically routes to the login page, or else it continues to go on any route in the website and that too without having the localstorage value.
Why's this happening ? please help me
Try this
//Checks if currentUser property still exists
if (!$localStorage.hasOwnProperty("currentUser")) {
$location.path('/login');
}

clear text input on another controller

is it possible to clear all fields in one controller by clicking on a button from the previous controller?
I'm trying to do so by setting cache: false in routes.js in the controller that needs to be cleared, however, I realized that it clears the controller's fields every time it's loaded.
I need to be able to clear the fields of the pages once a user clicks on login, however, I also need to be able to go back to the previous pages once I enter the "review info" page.
How should I go about this?
If you are using ionic version-1 framework, then use
$scope.logout = function(){
// first, clear the history
$ionicHistory.clearHistory();
// clear the cache before you navigate to a page
$ionicHistory.clearCache().then(function(){
$state.go("app.login");
});
}

Page refresh wipe out the Angularjs $scope variables

I'm new to Angularjs, I trying to implement the Facebook login through my Angularjs app. I was successful in implementing it. :)
What I'm doing is, if the login successful I'm setting a variable logged to true.
//loading the file
$scope.logged = false;
Facebook.getLoginStatus(function(response) {
if (response.status == 'connected') {
$scope.logged = true;
//do some stuff
}
else
$scope.login();
});
But my problem is, if the user refresh the page, the $scope.logged variable becomes false again and user is asked to re-login.
I'm using a REST API (Rails) as the back end
How can I avoid these kind of situations with Angular?
Put logged_in = true to cookieStore in your login method after authentication as below.
$cookieStore.put('logged_in',true);
$rootScope.logged_in = true;
and in your Controller, do
$rootScope.logged_in = $cookieStore.get('logged_in');
Now you can use this logged_in variable anywhere in the UI to check if the user is logged in. Make sure to use 'ngCookies' module in your app. and pass the $cookieStore dependency to your controller. You can even keep the user object itself similar to logged_in variable in cookies and retrieve it from cookies. Make sure to do logged_in = false and clear other variables in cookies and set it to blank in your logout method.

AngularJS (Restangular): Making a promise block? Need to use it for validating a token

I have stumbled upon Restangular for making calls to a rest service. It works great and returns a promise. I need to be able to have the call block. The reason for this is on a fresh page reload I am technically not loggged in but I may have a token stored in a cookie. i would like to validate this token against a rest service. Problem is that I need it to block.
If a timeout occurs or if its not valid that i can treat teh user as not authenticated.
This is the reason for wanting to block is that i would like to redirect them using $location.path to a new URL it not a valid token.
This doesn't happen on a specific route so i can't use resolve which is blocking. It technically happens on every route - I use the $on.$routeChangeStart and check an internal variable got LoggedIn or not, if not logged in i check for the stored token.
This happens on each Page refresh but not while navigating inside the application.
The affect I am trying to get is how Gmail works.
Look forward to any insight anyone has on this
Thanks
Basically you need to ensure that some asynchronous action occurs prior to any route change occurring, and in this case the action is authenticating a user.
What you can do is use the $routeChangeStart event that's emitted in order to add a property to the resolve object on the route like so:
function authenticate() {
if ( user.isAuthenticated ) {
return;
}
// Just fake it, but in a real app this might be an ajax call or something
return $timeout(function() {
user.isAuthenticated = true;
}, 3000);
}
$rootScope.$on( "$routeChangeStart", function( e, next ) {
console.log( "$routeChangeStart" );
next.resolve = angular.extend( next.resolve || {}, {
__authenticating__: authenticate
});
});
Since angular will wait for any promises in the resolve object to be fulfilled before proceeding, you can just use a pseudo dependency as in the example. Using something like that, you should be able to guarantee that your user is authenticating prior to any routes successfully executing.
Example: http://jsfiddle.net/hLddM/
I think the best way to do this might be to push the user around with $location.path, You can use .then() to effectively force a wait by leaving the user on a loading page.
var currentPath = $location.path();
$location.path(loadingScreen);
//Assuming you have some sort of login function for ease.
Restangular.login(token).then(
function(result) {
$location.path(currentPath)
},
function(error) {
$location.path(logInScreen)
}
);
If you're using ui-router, you could move to another state with the same URL, where you'd use that Restangular.login with the then, and in case of success go back to the "logged in" state, otherwise, go to the "log in" state where the user must enter his username and password.
If you're not using ui-router, you could implement something like that with some ng-switch.
So, upon arrival to the screen, you do that Restangular.login and by default you show loading page by setting some boolean to true. Then, if it doesn't succedd, you send him to the login, otherwise, you set loading to false and show page.
Anyway, I'd strongly recommend using ui-router, it rocks :)
Hope this works!

Resources