Background:
I have a multi page angularjs application. I have a service factory object that I load with values in my initial page. The values loaded to the service factory object are available in the different views or pages via their corresponding controller js. The value provided by the user is lost if the user tries to do a browser refresh by clicking F5 button.
My issue:
When the application is loaded the 'loginView' is displayed, the userId and password entered by the user is passed to the second view (summaryView.html). And i can see the userId and password displayed correct in the second page. But if i refresh my second view (summaryView.html) then I loose all the values. The application is sort of reset.
I would like to retain the user supplied data even after the browser is refreshed or reloaded.
My code:
**index.html**
<div ng-app="offlineInspectionApp">
<div ng-view></div>
</div>
<script>
var mainApp = angular.module("offlineInspectionApp", ['ngRoute']);
mainApp.factory( 'AuthService', function() {
var userCore = {userId : "anonymous" , password: "password", status :"online"};
return {userCore: function() { return userCore; }};
});
mainApp.config(['$routeProvider',
function($routeProvider) {
$routeProvider.
when('/summary', {
templateUrl: 'summaryView.html',
controller: 'SummaryViewController'
}).
when('/login', {
templateUrl: 'loginView.html',
controller: 'LoginViewController'
});
}]);
**LoginViewController.js**
angular.module("offlineInspectionApp").controller('LoginViewController', function($scope,$http,$location, AuthService) {
$scope.authenticateUser = function() {
AuthService.userCore.userId = $scope.userId;
AuthService.userCore.password = $scope.password;
$location.path( "/summary" );
}
});
**SummaryViewController.js**
angular.module("offlineInspectionApp").controller('SummaryViewController', function($scope,$http,$location, AuthService) {
$scope.syncInspectionDetails = function(inspectionId) {
alert(AuthService.userCore.userId +' '+ AuthService.userCore.password);
};
I have two html files 'loginView.html' and 'summaryView.html'
Flow
1- when the user enter the correct username and password you store the data in angular variables. this is fine and it redirect to summary page. AuthService.userCore has the same scope over the summery page so it displays the details on first attempt.
2- when you refresh the page all the variable you declared in angularJs are cleared. So when you refresh the page you didn't get those variables.
Solution
there are two ways
1- either store the whole user data in cookie, and fetch the data from cookie on refresh.
2- one sign in complition use any access token and store it in cookie. And check for the access token and fetch the data from backend again on every refresh.
Related
I am new to AngularJS web development.
STEP 1. During initialization, I get login information from a server with http call. Say, UserName, UserID and some other information.
STEP 2. After successful http call, I would like to populate the loginObj object such as
$scope.loginObj = { UserID = '', UserName = '', SomeData: '' };
$scope.loginObj.UserID = 1000;
$scope.loginObj.UserName = 'John Doe';
$scope.loginObj.SomeData = 'Some other data';
STEP 3. I would like to broadcast $scope.loginObj object information with
$rootScope.broadcast method.
All the examples I have seen used some kind of click button. No Button Click
solution.
STEP 4. In the child controller, I would like to receive the broadcasted
information from the Parent Controller.
How can I receive this information?
STEP 5. Some times I get some extra information at the Child Controller as well.
How can I receive this information from Child controller to the Parent
Controller?
Please provide me a solution or direct me some sites where I can get the example.
Instead of using broadcast, create an angularjs service in which you persist the login info you got from http call and you can inject this service in the controller in which you need login info.
create a service like this :
/*app is your angular module name*/
app.factory('authFactory',['$state',function( $state){
var authFactory = {
currentUser: {},
setCurrentUser: function(userinfo){
authFactory.currentUser = userinfo;
},
getCurrentUser: function(){
return authFactory.currentUser;
}
};
return authFactory;
}
in your login controller, inject authFactory, then once user is logged in, call authFactory.setCurrentUser and pass an object ({login: userlogin, email: useremail}). if you need the logged in user in another page, just inject authFactory in that page and call authFactory.getCurrentUser().
I am using angularjs & cordova in my app. I am stuck at one point i have an button which is used to authorize a person or user. It sends me to the link where i want to allow the user to access. It is getting access and the url of the link shows that the user is http://(websitename).com/approve but how can i get back the user token into my app so that token can be used for further purpose and second thing how can i send my user from the accessing window back to the app.
HTML code:
<button ng-click="login()">Login</button>
Controller code:
$scope.login = function () {
angular.element(document).ready(function () {
var url = 'https://(website_name).com/1/authorize';
var key = 'My App key';
var callbackURl = 'http://localhost/myApp/';
loginService.login(url,key,callbackURl);
});
factory code:
.factory('loginService', function($http,$window){
return {
login: function(url,key,callbackURl){
var clientURL = url+'?callback_method=postMessage&return_url='+encodeURIComponent(callbackURl)+'&expiration=never&name=myApp&response_type=token&key='+encodeURIComponent(key);
var clientWindow = window.open(clientURL,"_blank");
}
}
})
I want to callback my user along with the token to 'http://localhost/myApp/'
how can it be done or is there any easier way to do such queries??
-thanks in advance.
I'd like to know the best practice, how to set up routing and templates in AngularJS to show a different front & login area to visitors, and then show a dashboard to logged in users on the same base url ('/').
The two pages are structurally completely different, and also different assets are needed.
Is it better to setup two different apps for the 2 parts of the website, but then how would I manage the session between the 2?
Or is it better to make an "empty" layout with nothing between the body tags an load the different templates into that, and make separate routing for the front part and the dasboard part?
I'm looking for kind of like the way Facebook's login is made. To stay on the root domain after logging in.
I spent my afternoon Googling and searching SO, but couldn't find any guides on this. Any ideas how you usually do this kind of separation in AngularJS would be very welcome.
Martin's answer is fine, but I'd rather solve the problem with ui-router module:
Create three states: root, dashboard and landing.
Capture URL with root state and redirect to dashboard or landing depending on authorization status.
dashboard and landing will have controller and templateUrl defined in one place together with other application states, which is nice.
Code example:
angular
.module("app", ["ui.router"])
.value("user", {
name: "Bob",
id: 1,
loggedIn: true
})
.config(function($stateProvider) {
$stateProvider
.state("root", {
url: "",
template: "<section ui-view></section>",
controller: function($state, user) {
if ($state.is("root")) $state.go(user.loggedIn ? "dashboard" : "landing");
}
})
.state("landing", {
templateUrl: "landing.html",
controller: "LandingCtrl"
})
.state("dashboard", {
templateUrl: "dashboard.html",
controller: "DashboardCtrl"
});
})
.controller("DashboardCtrl", function($scope, user, $state) {
$scope.logout = function() {
user.loggedIn = false;
$state.go("root");
}
})
.controller("LandingCtrl", function($scope, user, $state) {
$scope.login = function() {
user.loggedIn = true;
$state.go("root");
}
})
Complete example on Plunker.
You can use the same master template, include different partials depending on if the user is logged in or not.
<ng-include=" 'views/loggedout.html' " ng-if="!loggedIn"></ng-include>
<ng-include=" 'views/loggedin.html' " ng-if="loggedIn"></ng-include>
In angular Js i am trying to store user data such as profile name that should exist in most of routes is it a good practice to store them in the $rootScope. IF not where should i store them.
If you use a service it's everywhere available and if it should be persistent over page reloads and so on, then you can store the data in local storage or a cookie etc. and access it with your service on load.
angular.module('app')
.factory('UserService', ['SessionService', function(SessionService) {
SessionService.load();
var user = SessionService.getUser();
var service = {
setUser: function(u){ user = u; },
getUser: function(){ return user; }
};
return service;
}])
.controller('DemoCtrl', ['$scope', 'UserService', function($scope, UserService){
$scope.user = UserService.getUser();
}]);
I'm new to angular myself but the route I'm taking is to write a service. You could have a service that stores the user profile data. I would maybe put a method on the service to load the profile data and then store it locally in the service. You could then get this information via a getter method.
I have an index.html page that has a $routeProvider inside. Whenever I go on a new path inside this page, I check to see if the user is logged in. Something like this:
myApp.run(function($rootScope, $location, authService) {
$rootScope.$on("$routeChangeStart", function (event, next, current) {
$rootScope.title = next.$$route.title;
authService.isLogged().then(null, function() {
$location.path('/login');
});
});
});
I have a separate page called login.html. If the user is not logged in, I want a javascript line to redirect him to login.html. With this example I copy / pasted , if I have the URL
localhost/myapp/#/home
it redirects me to
localhost/myapp/#/login
but I want it to redirect me to
localhost/myapp/login
widthout #.
You can just use plain js, if your base is allways /myapp, login is enough:
$window.location.href = 'login'; //If you care about testability
window.location.href = 'login'; //If you don't