When page refresh, how to call back function in angularjs - angularjs

I'm trying to maintain session after page refresh in angularjs using java. I have seen many examples but, i didn't find proper solution which exactly I'm looking for.
Please find below login snippet code, when i click on login button it is calling loginUser()function in LoginController
When i do page refresh it is going to LoginController but it is not going inside loginUser()function.
According to my knowledge until we call function, it doesn't goes inside of it.
When I do refresh how can i call back loginUser() function.
please help me out from these. Appreciated..Many thanks.
LoginController.js
function LoginController($scope, $http, $location, $rootScope,
userService, SessionIdService) {
$scope.user = {};
$scope.user.username = '';
$scope.user.password = '';
$rootScope.loginUser = function(username, password) {
$scope.resetError();
$http.post('/user/main/login/' + username, password).success(
function(login) {
if (login.sessionId === null) {
$scope.setError(login.status);
return;
} else {
$rootScope.userlogin = login.uname;
userService.setUserName(login.uname);
SessionIdService.setSessionId(login.sessionId);
$location.path("/home");
}
}).error(function() {
$scope.setError('Invalid user/password combination');
});
};
$scope.resetError = function() {
$scope.error = false;
$scope.errorMessage = '';
};
$scope.setError = function(message) {
$scope.error = true;
$scope.errorMessage = message;
$rootScope.sees = '';
$rootScope.userlogin = '';
};
};
app.js
app.run(function($rootScope, $location, SessionIdService) {
$rootScope.$on("$routeChangeStart", function(event, next, current) {
console.log("Routechanged... ");
if (SessionIdService.getSessionId == "true") {
if (next.templateUrl == "scripts/views/homescreen.html") {
$location.path("/home");
} else {
$location.path("/screen");
}
}
});
});
login.html
<input name="textfield" type="text" ng-model="user.username"/>
<input name="textfield" type="password" ng-model="user.password"/>
<button type="button" ng-lick="loginUser(user.username,user.password)">Login</button>

It is not clear to me why you want to call loginUser after page refresh. Isn't the user already logged in? I think what you want is to call the success function inside the loginIser. In that case, you need to embed that data as a global JS variable inside your Java template, and pass that to your controller somehow.
You probably want these to be run after refresh:
$rootScope.userlogin = login.uname;
userService.setUserName(login.uname);
SessionIdService.setSessionId(login.sessionId);
$location.path("/home");
So, in your Java template, do something like:
<script>window.UNAME = {% this comes from your database %};window.SESSIONID={% similar %}</script>
Then, call that function somehow with window.UNAME as input. (or in your controller, check for the existence of window.UNAME and call it immediately. Something like:
window.UNAME && function (name, sessionId) {
$rootScope.userlogin = uname;
userService.setUserName(uname);
SessionIdService.setSessionId(sessionId);
$location.path("/home");
) {
}(window.UNAME, window.SESSION_ID)
Some other recommendations (unrelated to your main problem probably):
First of, change $rootScope.loginUser = function(username, password) { to
$rootScope.loginUser = function() {
var username = $scope.user.username;
var password = $scope.user.password
since you already have access to username and password there. So, change ng-click="loginUser()".
Second, SessionIdService.getSessionId == "true" seems off, check should probably be just SessionIdService.getSessionId

Related

Angular chat client - 2 views with one controller

I build chat function in my web app and i am about to create chat functionality between logged clients. Here is my screen from application to show exactly what i want to solve
Screen of my app
As you can see i got list of online users stored in scope in sidebar. Its created as partial view in my Asp.Net with .cshtml and i render content in "white box" using angular routing.
Problem is i use same controller twice and it creates new scope for each html so i got data in my sidebar, but in my content view i dont have any data. I am thinking about passing my data to rootscope, but i dont know if its good idea.
So my question is. Is there anything how i can clone my data from one controller to another or how i can solve this without changing functionality and if i can keep my views controlled with one controller.
Here is my PrivateChatController.js
(function () {
'use strict';
app.controller('PrivateChatController', ['$rootScope', '$scope', 'SignalRService', '$location', 'PrivateChatService', PrivateChatController]);
function PrivateChatController($rootScope, $scope, SignalRService, $location, PrivateChatService) {
//angular stuff
$scope.online_users = [];
$scope.isChatHidden = false;
$scope.openPrivateChatWindow = function (index) {
// $scope.isChatHidden = true;
angular.forEach($scope.online_users, function (value, key) {
if (index == key) {
$rootScope.currentPrivateChatUser = ({
UserName: value.UserName,
ConnectionId: value.connectionId,
});
$location.path("/details/" + value.UserName);
}
});
};
$scope.closePrivateChatWindow = function (index) {
$scope.isChatHidden = false
};
//signalR stuff
var chatHub = $.connection.chatHub;
$.connection.hub.logging = true;
chatHub.client.foo = function () { };
registerClientMethods(chatHub);
$.connection.hub.start()
.done(function(){ console.log('Now connected, connection ID=' + $.connection.hub.id); })
.fail(function () { console.log('Could not Connect!'); });
function registerClientMethods(chatHub) {
//user object
chatHub.client.newOnlineUser = function (user) {
var newUser = ({
connectionId: user.ConnectionId,
UserName: user.UserName
});
$scope.online_users.push(newUser);
$scope.$apply();
};
//compare scope online users with server list of online users
chatHub.client.getOnlineUsers = function (onlineUsers) {
//loop through scope
angular.forEach($scope.online_users, function (scopeValue, scopeKey) {
//loop through received list of online users from server
angular.forEach(onlineUsers, function (serverListValue, serverListKey) {
if (!(serverListValue.ConnectionId == scopeValue.connectionId)) {
var newUser = ({
connectionId: serverListValue.ConnectionId,
UserName: serverListValue.UserName
});
$scope.online_users.push(newUser);
$scope.$apply();
}
})
})
};
chatHub.client.onUserDisconnected = function (id, user) {
var index = 0;
//find out index of user
angular.forEach($scope.online_users, function (value, key) {
if (value.connectionId == id) {
index = key;
}
})
$scope.online_users.splice(index, 1);
$scope.$apply();
};
}};})();
Consider using services as a layer for data sharing. It should also contain chat related logic, in my opinion controllers should be as thin as possible.
Move chatHub.client.getOnlineUsers function to the service and create getter for users.
Further read

Firebase function not running until view change [duplicate]

This question already has an answer here:
How come Angular doesn't update with scope here?
(1 answer)
Closed 6 years ago.
I have a Firebase function inside an angular controller. There is a button that when clicked takes the selected option and the type input and stores them into the user's object like so:
{
selected-option : input-value
}
This works perfectly, but only works when the view is changed. In my case both airlines already have data so this function displays an $ionicPopup.
After the view has changed once the functionality is absolutely perfect. This is obviously a problem and I assume it is an $apply or $digest issue.
Here is my controller code (Supected location marked by "ISSUE RIGHT HERE"):
.controller('ProgramCtrl', ['$scope', '$state', '$firebaseArray', 'facebook', '$ionicPopup', '$ionicLoading',
function($scope, $state, $firebaseArray, facebook, $ionicPopup, $ionicLoading) {
$scope.goBack = function() {
$state.go('app.home');
}
$scope.show = function() {
$ionicLoading.show({
template: 'Loading...'
});
};
$scope.hide = function(){
$ionicLoading.hide();
};
// Get who is logged in
$scope.user = facebook.get();
// Array of airlines
var airRef = ref.child("airlines");
$scope.airlines = $firebaseArray(airRef);
$scope.selectedAir = {};
$scope.miles = {};
$scope.revealInput = function(num) {
// Jquery variables
$milesPoints = $(".milesPoints");
$saveTicket = $(".saveTicket");
// Will fade in visibility depending on num passed into function
switch(num) {
case 1:
$saveTicket.prop("disabled", false);
$saveTicket.fadeTo(400, 1);
break;
default:
break;
}
}
// Add program to user
$scope.addProgram = function () {
// Connect to Firebase
Firebase.goOnline();
// Check for facebook user
if(jQuery.isEmptyObject($scope.user)) {
// Get Firebase user
var authData = ref.getAuth();
var theUser = ref.child("users").child(authData.uid);
var selected = {};
// Access user miles data
// $scope.show();
// ISSUE RIGHT HERE
theUser.child("miles").child($scope.selectedAir.name.$id).once("value", function(snapshot) {
// Update scopes
var exist = snapshot.exists();
// Check if object id exists, if so notify user
if(!exist) {
// Save and update program to user object
selected[$scope.selectedAir.name.$id] = $scope.miles.num;
theUser.child("miles").update(selected);
//$scope.hide();
$state.go("app.saved");
} else {
// Popup alert
var alertPopup = $ionicPopup.alert({
title: 'Oops!',
template: "You already created this airline! Go to the 'Add Ticket' page to add more points."
});
alertPopup.then(function(res) {
console.log("You already created this airline! Go to the 'Add Ticket' page to add more points.");
});
}
})
} else {
var theUser = ref.child("users").child($scope.user.id);
var selected = {};
$scope.show();
theUser.child("miles").child($scope.selectedAir.name.$id).once("value", function(snapshot) {
var exist = snapshot.exists();
if(!exist) {
selected[$scope.selectedAir.name.$id] = $scope.miles.num;
theUser.child("miles").update(selected);
$scope.hide();
$state.go("app.saved");
} else {
var alertPopup = $ionicPopup.alert({
title: 'Oops!',
template: "You already created this airline! Go to the 'Add Ticket' page to add more points."
});
alertPopup.then(function(res) {
console.log("You already created this airline! Go to the 'Add Ticket' page to add more points.");
});
}
})
}
}
}])
Thanks for the help and I can provide more code or screenshots if needed.
The issue is in this piece of code:
theUser.child("miles").child($scope.selectedAir.name.$id).once("value", function(snapshot) {
$timout(function() {
var exist = snapshot.exists();
// Check if object id exists, if so notify user
if(!exist) {
// Save and update program to user object
selected[$scope.selectedAir.name.$id] = $scope.miles.num;
theUser.child("miles").update(selected);
//$scope.hide();
$state.go("app.saved");
} else {
// Popup alert
var alertPopup = $ionicPopup.alert({
title: 'Oops!',
template: "You already created this airline! Go to the 'Add Ticket' page to add more points."
});
alertPopup.then(function(res) {
console.log("You already created this airline! Go to the 'Add Ticket' page to add more points.");
});
}
});
})
When you call once(), it starts loading data from Firebase. Since this may take some time, you pass in a callback function that is invoked when the data is available. But by the time the callback function is invoked, AngularJS is not expecting updates to the $scope anymore.
The solution is to wrap the code into a $timeout(), which ensures it gets executed when AngularJS is ready to handle scope changes again:
theUser.child("miles").child($scope.selectedAir.name.$id).once("value", function(snapshot) {
// Update scopes
var exist = snapshot.exists();
// Check if object id exists, if so notify user
if(!exist) {
// Save and update program to user object
selected[$scope.selectedAir.name.$id] = $scope.miles.num;
theUser.child("miles").update(selected);
//$scope.hide();
$state.go("app.saved");
} else {
// Popup alert
var alertPopup = $ionicPopup.alert({
title: 'Oops!',
template: "You already created this airline! Go to the 'Add Ticket' page to add more points."
});
alertPopup.then(function(res) {
console.log("You already created this airline! Go to the 'Add Ticket' page to add more points.");
});
}
})
Note that this problem wouldn't happen if you used AngularFire's $firebaseObject() and $firebaseArray() primitives, since those automatically notify AngularJS of scope changes.
We get this question a lot. Here's a recent one: Taking long to load

angularjs singleton doesn't work

In app.js I have a variable that I use in two files/controllers:
var app = angular.module('appDemo', ['MainControllers', 'MainServices'])
.constant('myConfig', {
'backend': 'http://localhost:1236'
})
.service('mailService', function() {
var mail = {
value: 'hello world'
};
var getMail = function() {
return mail;
}
var setMail = function(email) {
mail.value = email;
}
return {
getMail: getMail,
setMail: setMail
};
);
Setting the variable from controllerOne goes fine:
angular.module('MainControllers')
.controller('MemberController', function ($scope, mainService, appDemo) {
window.onbeforeunload = function (e) {
appDemo.setMail('test#test.com');
};
But when I get the setting variable from the controllerTwo than I get the default value:
angular.module('MainControllers')
.controller('EmailController', function($scope, appDemo) {
$scope.mailAddress = appDemo.getMail();
});
Each controller is in separate file.
what is wrong?
This may be because the service itself is being reloaded because as I can see you are setting the mail in the first controller on onbeforeunload.
Services can't persist on window reloads or page refresh. They get reloaded hence reinitialized every time you reload the page.
If you want to persist the values try putting it in localStorage or sessionStorage.

Angular.js edit in place with password

This is my example here
I want to add password protect, when i click to "Edit title".
How can i do it?
JS code:
function ClickToEditCtrl($scope) {
$scope.title = "Welcome to this demo!";
$scope.editorEnabled = false;
$scope.enableEditor = function() {
$scope.editorEnabled = true;
$scope.editableTitle = $scope.title;
};
$scope.disableEditor = function() {
$scope.editorEnabled = false;
};
$scope.save = function() {
$scope.title = $scope.editableTitle;
$scope.disableEditor();
};
}
Simply create a $scope.checkPassword (or something meaningful) function which shows a popup/modal/etc where the user can input the password and then make an ajax call to verify for the password. If the password entered is correct enable editor else do nothing. Or maybe you want to allow save password if the user authenticates successfully.
UPDATE:
I think password verification should be handled totally by the server. I would make a call to function that handles authentication before saving the password (on the server). So make sure that you send the password as a parameter with the save call.

AngularJS - change $location silently - remove query string

Is there any way to silently change the route in the url bar using angular?
The user clicks a link for the email that goes to:
/verificationExecuted?verificationCode=xxxxxx
When the page loads I want to read the verificationCode and then clear it:
if($location.path() == '/verificationExecuted'){
this.registrationCode = this.$location.search()["verificationCode"];
this.$location.search("verificationCode", null); //Uncomment but make this silent!
if(registrationCode != null) {
....
}
else $location.path("/404");
}
What happens when I clear it is the remaining part of the route ("/verificationExecuted") remains buts the route re-triggers so it comes around again with no verificationCode and goes straight to 404.
I want to remove the code without doing anything else.
You can always set the reloadOnSearch option on your route to be false.
It will prevent the route from reloading if only the query string changes:
$routeProvider.when("/path/to/my/route",{
controller: 'MyController',
templateUrl: '/path/to/template.html',
//Secret Sauce
reloadOnSearch: false
});
try this
$location.url($location.path())
See documentation for more details about $location
I had a similar requirement for one of my projects.
What I did in such a case was make use of a service.
app.factory('queryData', function () {
var data;
return {
get: function () {
return data;
},
set: function (newData) {
data = newData
}
};
});
This service was then used in my controller as:
app.controller('TestCtrl', ['$scope', '$location', 'queryData',
function ($scope, $location, queryData) {
var queryParam = $location.search()['myParam'];
if (queryParam) {
//Store it
queryData.set(queryParam);
//Reload same page without query argument
$location.path('/same/path/without/argument');
} else {
//Use the service
queryParam = queryData.get();
if (queryParam) {
//Reset it so that the next cycle works correctly
queryData.set();
}
else {
//404 - nobody seems to have the query
$location.path('/404');
}
}
}
]);
I solved this by adding a method that changes the path and canceling the event.
public updateSearch(){
var un = this.$rootScope.$on('$routeChangeStart', (e)=> {
e.preventDefault();
un();
});
this.$location.search('new',search.searchFilter);
if (!keep_previous_path_in_history) this.$location.replace();
}

Resources