Login.js:
app.controller('LoginFormController', ['$scope','$http','$rootScope', '$state', function($scope, $http, $rootScope, $state) {
$scope.user = {};
$scope.authError = null;
$scope.login = function() {
$scope.authError = null;
var emailId = $scope.user.email;
var password = $scope.user.password;
$http({
url: 'http://localhost:8090/login/login',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
data: 'email='+emailId+'&password='+password
//data: {'email': $scope.user.email, 'password': $scope.user.password}
}).then(function(response) {
console.log(response.data);
if (response.data.status == 'SUCCESS') {
$scope.user = response.data.user.firstName;
$rootScope.test = response.data.user.firstName;
console.log("check: ",$rootScope.test)
$state.go('app.dashboard');
} else {
//alert('invalid login');
$scope.authError = 'Email or Password not right';
}
}, function(x) {
$scope.authError = 'Server Error';
})
};
}])
I saved the value under $rootScope.test
Here Is my App.main.js:
'use strict';
angular.module('app').controller('AppCtrl', ['$scope','$rootScope',
function($scope, $rootScope) {
$scope.user5 = $rootScope.test;
}
]);
trying to print the rootscope
If I run this Code i am facing the error of $rootScope is undefined in the console. How to Resolve this
$rootScope is the parent of all $scope, each $scope receives a copy of $rootScope data which you can access using $scope itself.
Here is a modified version
https://jsfiddle.net/sedhal/g08uecv5/17/
angular.module('myApp', [])
.run(function($rootScope) {
$rootScope.obj = {
"name":"user1",
"bdate":"18/11/1994",
"city":"Ahmedabad"
};
})
.controller('myCtrl', function($scope, $rootScope) {
$scope.data = $rootScope.obj;
})
.controller('myCtrl2', function($scope, $rootScope) {
$scope.data1 = $rootScope.obj;
});
There is a useful answer to your question here: https://stackoverflow.com/a/18881189/9013688
Instead of passing directly your property on the $rootScope, you could emit an event which could be listened in an other part of your app like this:
if (response.data.status == 'SUCCESS') {
$rootScope.$emit('user-logged', response.data.user.firstName)
}
And then:
$rootScope.$on('user-logged', function(event, data){
do something with your data
})
Or you could use a service which is a good way to handle your data in all your app.
Please ensure that you take the advice of georgeawg, his suggestion seems to be the best way to implement this functionality in my opinion.
I want to suggest what might be wrong with your example.
If you can see that in the main App.main.js you have given the declaration as
angular.module('app').controller(...
But you are using a variable app in login.js like so.
app.controller(...
Which I am assuming you are creating somewhere else. Thus the set rootscope value is lost because there are two instances of the same app.
The solution to your problem will be to declare one variable app which will store the instance of the app. So the fix for your solution will be to modify App.main.js to be like so.
var app = angular.module('app');
app.controller(...
Also you need to remove any other arbitary var app = in your complete code, since these will create multiple instances of the same app.
I hope my explanation was understandable and the correct guess, please try out this solution!
In your main js add this.
app.run(['$rootScope', function($rootScope) {
$rootScope.test;
}]);
Here is a sample implementation of george's suggestion which is the proper way to handle this.
app.controller('LoginFormController', ['$scope','$http','$rootScope', '$state', 'stateService', function($scope, $http, $rootScope, $state, stateService) {
var userFirstName = 'John';
stateService.setFirstName('Bill');
userFirstName = stateService.getFirstName();
console.log(userFirstName); // result will be 'Bill'
}])
And the service which I usually call stateService
app.factory('stateService', [factory]);
function factory() {
var userFirstName = null;
stateService.getFirstName = function() {
return userFirstName;
};
stateService.setFirstName = function(firstName) {
userFirstName = firstName;
};
return stateService;
}
Related
I want to find the ID of the logged in user and display it in a page. I am new to angular and I don't have much clue on how to handle a session..
I have an angular app which is connected to backend API (.net core).
I will show the instances where $rootScope is used in the website (login and authorization is already enabled). I need to get an understanding of this to learn the app.
In App.js :
//Run phase
myApp.run(function($rootScope, $state) {
$rootScope.$state = $state; //Get state info in view
//Should below code be using rootScope or localStorage.. Check which one is better and why.
if (window.sessionStorage["userInfo"]) {
$rootScope.userInfo = JSON.parse(window.sessionStorage["userInfo"]);
}
//Check session and redirect to specific page
$rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams){
if(toState && toState.data && toState.data.auth && !window.sessionStorage["userInfo"]){
event.preventDefault();
window.location.href = "#login";
}
if(!toState && !toState.data && !toState.data.auth && window.sessionStorage["userInfo"]){
event.preventDefault();
window.location.href = "#dashboard";
}
});
});
Users.js :
'use strict';
angular.module('users', []);
//Routers
myApp.config(function($stateProvider) {
//Login
$stateProvider.state('login', {
url: "/login",
templateUrl: 'partials/users/login.html',
controller: 'loginController'
});
//Factories
myApp.factory('userServices', ['$http', function($http) {
var factoryDefinitions = {
login: function (loginReq) {
$http.defaults.headers.common['Access-Control-Allow-Origin'] = '*';
return $http.post('http://localhost:1783/api/token?UserName='+loginReq.username+'&password='+loginReq.password).success(function (data) { return data; });
}
}
return factoryDefinitions;
}
]);
//Controllers
myApp.controller('loginController', ['$scope', 'userServices', '$location', '$rootScope', function($scope, userServices, $location, $rootScope) {
$scope.doLogin = function() {
if ($scope.loginForm.$valid) {
userServices.login($scope.login).then(function(result){
$scope.data = result;
if (!result.error) {
window.sessionStorage["userInfo"] = JSON.stringify(result.data);
$rootScope.userInfo = JSON.parse(window.sessionStorage["userInfo"]);
//$localStorage.currentUser = { username: login.username, token: result.data };
//$http.defaults.headers.common.Authorization = 'Token ' + response.token;
$location.path("/dashboard");
}
});
}
};
}]);
I came to know that the information about the user will be available in $rootScope.userInfo. If so, how can I take a value inside it?
Please explain with an example if possible. Thanks in advance.
One:
myApp.controller('loginController', [
'$scope', 'userServices', '$location',
'$rootScope',
function($scope, userServices, $location, $rootScope) {
Inside the controller, $rootScope was injected which makes you have access to the userInfo in that controller.
so if you inject $rootScope into another controller and console.log($rootScope.userInfo) you would see the users data.
myApp.controller('anotherController', ['$scope', '$rootScope', function
($scope, $rootScope){
console.log($rootScope.userInfo) //you'd see the users data from sessionStorage
});
According to this post on quora
$scope is an object that is accessible from current component
e.g Controller, Service only. $rootScope refers to an object
which is accessible from everywhere of the application.
You can think $rootScope as global variable and $scope as local variables.
$rootScope Defn.
In your case, once the user is logged in a key "userInfo" in sessionStorage is created and the same data is copied to $rootScope.userInfo. To check the fields in the userInfo after login try
console.log($rootScope.userInfo);
and print it in the console or open your session storage in your browser debugger tools [for chrome open developer tools>applications>sessionstorage>domainname] to view the values in the "userInfo" key.
Suppose you have
{
uid: "10",
fullname: "John Doe"
}
you can access uid in the script using $rootScope.userInfo.uid or $rootScope.userInfo['uid'].
Just in case you are unable to read the code, here is an explanation
if (window.sessionStorage["userInfo"]) {
$rootScope.userInfo = JSON.parse(window.sessionStorage["userInfo"]);
}
is checking the user is logged in or not.
the factory
myApp.factory('userServices', ['$http', function($http) {
var factoryDefinitions = {
login: function (loginReq) {
$http.defaults.headers.common['Access-Control-Allow-Origin'] = '*';
return $http.post('http://localhost:1783/api/token?UserName='+loginReq.username+'&password='+loginReq.password).success(function (data) { return data; });
}
}
is calling the server to get the userInfo object.
$scope.doLogin = function() {
if ($scope.loginForm.$valid) {
userServices.login($scope.login).then(function(result){
$scope.data = result;
if (!result.error) {
window.sessionStorage["userInfo"] = JSON.stringify(result.data);
$rootScope.userInfo = JSON.parse(window.sessionStorage["userInfo"]);
//$localStorage.currentUser = { username: login.username, token: result.data };
//$http.defaults.headers.common.Authorization = 'Token ' + response.token;
$location.path("/dashboard");
}
});
}
};
$scope.doLogin is calling the above factory and storing the userInfo object.
Let's say I have the following files:
JS1 file:
var app = angular.module('myApp', []);
app.controller('myCtrlOfJs1', function ($scope, $http) {
$http.post("url", data).success(function(data, status) {
$scope.hello = data;
})
})
JS2 file:
var app = angular.module('myApp', []);
app.controller('myCtrlOfJs2', function ($scope, $http) {
// $http.post("url", data).success(function(data, status) {
// $scope.hello = data;
// })
})
What I don't want is rewrite the same code twice. Then I want to call that function in my JS1 file, in the JS2 file. Is it possible?
PS: It's only an example, my code has much more lines than it.
Any help is appreciated. Thanks.
You can always use services: https://docs.angularjs.org/guide/services
app.factory('commonFeatures', function($http) {
return {
setHelloMsg: function(scope) {
$http.post("url", data).success(function(data, status) {
scope.hello = data;
})
}
};
});
app.controller('myCtrlOfJs1', function ($scope, commonFeatures) {
commonFeatures.setHelloMsg($scope);
});
edit:
As a response to your comment:
Well, it can be located nearly everywhere. Have a look at https://github.com/johnpapa/angular-styleguide/blob/master/a1/README.md#single-responsibility. There are more style guides, but I personally follow this one and it just makes sense.
Your view doesn't have to change at all.
In general, you want to separate common functionality like this out into angular services: https://docs.angularjs.org/guide/services
In this example it might look like this:
var andyModule = angular.module('anyModule', []);
andyModule.factory('helloDataService', function($http) {
var helloDataService = {
// returns a promise
getHelloData = function() {
return $http.post("url", data)
}
};
return shinyNewServiceInstance;
});
And in your controller
app.controller('myCtrlOfJs1', function ($scope, $http, helloDataService) {
helloDataService.getHelloData().success((data)=> {
$scope.data = data;
})
})
I would abstract this to a service. Services are particularly good spots for things like network calls.
By the way using angular.module("app", modules) syntax will create an app named app, so JS2 file will overwite the module from JS1. I doubt you intend this.
angular.module("app", []);
var app = angular.module('myApp');
app.controller('myCtrlOfJs1', function ($scope, hello) {
hello.post().then(data => scope.$hello = data);
});
var app = angular.module('myApp');
app.controller('myCtrlOfJs2', function ($scope, hello) {
hello.post().then(data => scope.$hello = data);
});
app.factory("hello", function ($http) {
// set data somehow
return {
post() {
return $http.post("url", data);
},
};
});
This still duplicates the scope.$hello code which may be what you want to avoid. In this case you can extend from another controller that implements this either using newer class syntax or through the prototype. In this case I think it would be better to use controllerAs instead of $scope.
This is a method you can achieve what you are looking for.
I prefer the service method though
Take a look at this :
use case for $controller service in angularjs
https://docs.angularjs.org/api/ng/service/$controller
Hope it helps
I'm trying to pass data from one controller to another using a service, however no matter what I'm trying it always returns 'undefined' on the second controller. Here is my service :
app.service('myService', ['$rootScope', '$http', function ($rootScope, $http) {
var savedData = {}
this.setData = function (data) {
savedData = data;
console.log('Data saved !', savedData);
}
this.getData = function get() {
console.log('Data used !', savedData);
return this.savedData;
}
}]);
Here is controller1 :
.controller('HomeCtrl', ['$scope','$location','$firebaseSimpleLogin','myService','$cookies','$window', function($scope,$location, $firebaseSimpleLogin, myService, $cookies, $window) {
loginObj.$login('password', {
email: username,
password: password
})
.then(function(user) {
// Success callback
console.log('Authentication successful');
myService.setData(user);
console.log('myservice:', myService.getData()); // works fine
}]);
And then controller2:
// Dashboard controller
.controller('DashboardCtrl', ['$scope','$firebaseSimpleLogin','myService',function($scope,$firebaseSimpleLogin, $location, myService) {
console.log('myservice:', myService.getData()); //returns undefined
}]);
That is simple code, unfortunately I've been struggling for a few hours now, any suggestion ? Thanks.
Created a fiddle here:
http://jsfiddle.net/frishi/8yn3nhfw/16
To isolate the problem, can you remove the dependencies from the definition for myService and see if that makes it work? Look at the console after you load the fiddle.
var app = angular.module('app', [])
.service('myService', function(){
this.getData = function(){
return "got Data";
}
})
I assume the issue is that you are returning this.savedData in the service. Try returning savedData.
this behaves different in Javascript than in other languages.
I'm trying to send a receive a response from a server using ngResource module of Angular. I'm using promises but it doesn't work, I think there might be something wrong with my code. It goes as it is :
Controller:
var LoginController = angular.module('LoginController', [
]);
LoginController.controller("LoginController", ['$scope','$location','LoginService', function($scope, $location, LoginService) {
$scope.user = {}
$scope.checkCredentials = function () {
var userCredentials = LoginService.get();
userCredentials.$promise.then(function(result){
$scope.user.login = response.login;
$scope.user.password = response.password;
});
};
}]);
Rest module:
var RestServices = angular.module('RestServices', ['ngResource']);
RestServices.factory('LoginService', ['$resource','$routeParams',
function($resource, $routeParams){
return $resource('/user',{},{
get: {method:'GET', isArray:false}
});
}]);
If I put the line:
var userCredentials = LoginService.get();
directly inside declaration of controller, it works and object user is filled properly and send to my view, but when I try to do that in a function invoked by clicking a button (like it is in my code) it doesn't fill user object properly. What might be wrong with my code?
Thanks in advance.
Change "result" to "response"!
var userCredentials = LoginService.get();
userCredentials.$promise.then(function(response){
$scope.user.login = response.login;
$scope.user.password = response.password;
});
But you can also achieve the same in a more succinct and idiomatic way:
LoginService.get(function(data){
$scope.user.login = data.login;
$scope.user.password = data.password;
});
I am trying to show single trail information on trailDetails.html when I click this link on my searchTrails.html. And there is nothing on trailDetails.html. But if I move codes in getDataService.js to searchTrailsController.js, everything will be ok. I don't figure out why. Could anybody give some suggestions?
app.js:
var app = angular.module("crowd", ["ngRoute"]);
app.config(function ($routeProvider){
$routeProvider.when("/",{
templateUrl:"views/searchTrails.html",
controller:"searchTrailsCtrl"
});
$routeProvider.when("/trails/:trailId", {
templateUrl: "views/trailDetails.html",
controller: "searchTrailsCtrl"
});
})
getDataService.js:
app.service("dataService", function ($http, $routeParams){
this.getSingleTrail = function (){
var trail = [];
$http.get("http://localhost:8080/DMW-skeleton-1.0/trail/findTrailByTrailId/" + $routeParams.trailId)
.success(function (data){
trail.push(data);
})
return trail
}})
searchTrailsController.js:
app.controller("searchTrailsCtrl", function ($scope, dataService ) {
$scope.trail = dataService.getSingleTrail();})
But there comes nothing in trailDetails.html:
<p>{{trail.trailInfo.trailDescription}}</p>
The problem is that your data coming asynchronously but you try save them synchronously.
Step by step:
You define variable trail = []
You return trail variable to controller
Server responds with data (but you already return trail)
You can solve this problem by using next code:
app.service("dataService", function ($http, $routeParams){
this.getSingleTrail = function (){
var trail = [];
return $http.get("http://localhost:8080/DMW-skeleton-1.0/trail/findTrailByTrailId/" + $routeParams.trailId);
}})
app.controller("searchTrailsCtrl", function ($scope, dataService ) {
$scope.trail;
dataService.getSingleTrail().success(function(data){
$scope.trail = data;
});
})