Unable to inject Services in .run in angular js - javascript

I want to inject service into my .run block, but when I inject it I cannot use them.
My code is :
.run(['AuthFactory', function ($state, $rootScope, AuthFactory, $location) {
console.log("Auth Factory :%O", AuthFactory);
AuthFactory.registerUserChangeHandler(function (currentUser) {
$rootScope.currentUser = currentUser;
});
AuthFactory.refresh().then(function (currentUser) {
console.log("Current User is", currentUser);
}, function (reason) {
// User is not Logged in
$location.path("login");
});
}]);
When I write this code I get error :
"app.js:120Uncaught TypeError: Cannot read property
'registerUserChangeHandler' of undefined"
If I simply inject AuthFactory in function then everything works fine, but now I want to inject UserService & use methods inside the service.
I tried injecting it in function but I am unable to use it.
Open for all suggestions.

You mess up in DI.
.run(['state', '$rootScope', 'AuthFactory', '$location',
function ($state, $rootScope, AuthFactory, $location) {
console.log("Auth Factory :%O", AuthFactory);
// ...
}]);

Mistake is,if you use array way of dependency injection , than you need to follow the sequence. For example as $state if first value in array, than inside controller callback the first value will represent $state.
.run(['$state','$rootScope','AuthFactory','$location', function ($state, $rootScope, AuthFactory, $location) {
console.log("Auth Factory :%O", AuthFactory);
// UserService.login({
// 'username': "guest",
// 'password': "guest"
// }, function () {
// $state.go("corporate_site.home", {reload:'true'});
// }, function () {
// $rootScope.error = "Login Failed. Invalid Credentials.";
// });
// $state.go("corporate_site.home", {reload: 'true'});
AuthFactory.registerUserChangeHandler(function (currentUser) {
$rootScope.currentUser = currentUser;
});
AuthFactory.refresh().then(function (currentUser) {
console.log("Current User is", currentUser);
}, function (reason) {
// User is not Logged in
$location.path("login");
});
}]);

Related

PassFactory.setNewPass is not a function, factory function not a function

Can't seem to get this factory to work properly.
I'm trying to do the $http requests from a factory.
But I'm getting this error of:
TypeError: PassFactory.setNewPass is not a function
Below is the code:
Factory
(function () {
angular
.module("myApp")
.factory('PassFactory', ['$http', function ($http) {
/*
var passFactory = {};
passFactory.setNewPass = function (newpass, user) {
return $http.post('/password/' + newpass, user, function (response) {
});
};
*/
return {
setNewPass: function (newpass, user) {
return $http.post('/password/' + newpass, user, function (response) {
});
}
};
}])
})();
Controller
(function () {
angular
.module("myApp")
.controller('PCtrl', ['$scope', '$location', '$rootScope', 'PassFactory', setHome]);
function setHome($scope, $location, PassFactory) {
$scope.login = function (user) {
if (user.newpassword == user.newpasswordconfirm) {
PassFactory.setNewPass(user.newpassword, user).then(function (response) {
$location.path("/");
});
}
};
}
})();
You have missed $rootScope in controller factory function. Always make sure the the order in dependency have been injected inside DI array, in same sequence you should ask for their instance inside its factory function.
angular
.module("myApp")
.controller('PCtrl', ['$scope', '$location', '$rootScope', 'PassFactory', setHome]);
//added $rootScope in 3rd place
function setHome($scope, $location, $rootScope, PassFactory) {

Use local storage to store AngularJS data

I am currently using $rootScope to store user information and whether or not the user is logged in. I have tried using $window.localStorage, but with no success. My goal is to have items in my navbar appear through an ng-show once a user is logged on, have their username appear in the navbar, individual user profile view, all users view, etc. I need a persistent login. I have the navbar working with $rootscope, but whenever I try and transition over to $window.localStorage, it fails. Here is the code using $rootScope:
mainModule
angular.module('mainModule', [
'ui.router',
...
])
.config(configFunction)
.run(['$rootScope', '$state', 'Auth', function($rootScope, $state, Auth) {
$rootScope.$on('$stateChangeStart', function(event, next) {
if (next.requireAuth && !Auth.getAuthStatus()) {
console.log('DENY');
event.preventDefault();
$state.go('login');
} else if (Auth.getAuthStatus() || !Auth.getAuthStatus()) {
console.log('ALLOW');
}
});
}]);
Auth Factory
angular.module('authModule').factory('Auth', ['$http', '$state', function authFactory($http, $state) {
var factory = {};
var loggedIn = false;
var userData = {};
factory.getAuthStatus = function() {
$http.get('/api/v1/auth')
.success(function(data) {
if (data.status == true) {
loggedIn = true;
} else {
loggedIn = false;
}
})
.error(function(error) {
console.log(error);
loggedIn = false;
});
return loggedIn;
}
return factory;
}]);
Login Controller
function SigninController($scope, $rootScope, $http, $state) {
$scope.userData = {};
$scope.loginUser = function() {
$http.post('api/v1/login', $scope.userData)
.success((data) => {
$scope.userData = data.data;
$rootScope.loggedIn = true;
$rootScope.userData = data;
$state.go('home');
})
.error((error) => {
console.log('Error: ' + error);
});
};
}
Nav Controller
function NavbarController($scope, Auth) {
$scope.loggedIn = Auth.getAuthStatus();
}
EDIT EDIT EDIT
Here is how I am using local storage. These are the only things that changed.
Login Controller
function SigninController($scope, $window, $http, $state) {
$scope.userData = {};
$scope.loginUser = function() {
$http.post('api/v1/login', $scope.userData)
.success((data) => {
$scope.userData = data.data;
$window.localStorage.setItem('userData', angular.toJson(data));
$window.localStorage.setItem('loggedIn', true);
$state.go('home');
})
.error((error) => {
console.log('Error: ' + error);
});
};
}
Auth Factory
angular
.module('authModule')
.factory('Auth', ['$http', '$window', '$state', function authFactory($http, $window, $state) {
var factory = {};
factory.getAuthStatus = function() {
$http.get('/api/v1/auth')
.success(function(data) {
if (data.status == true) {
$window.localStorage.setItem('loggedIn', true);
} else {
$window.localStorage.setItem('loggedIn', false);
}
})
.error(function(error) {
console.log(error);
$window.localStorage.setItem('loggedIn', false);
});
return $window.localStorage.getItem('loggedIn');
}
return factory;
}]);
I see a potential problem with your use of localStorage.getItem('loggedIn').
Because localStorage only stores strings, what you get back is actually a stringified version of the boolean that you put in. If the string 'false' gets returned, your check of !Auth.getAuthStatus() in main module for example will always evaluate to boolean false because any non-empty string in JavaScript is "truthy".
i.e. !'false' === false (the same as !true === false)
You can get over this by using JSON.parse on the value in localStorage. e.g. JSON.parse(localStorage.getItem('loggedIn')) would parse the string 'false' to the Boolean false.
Simply replace $window.localStorage with window.localStorage and you should be fine.
For example:
function SigninController($scope, $window, $http, $state) {
$scope.userData = {};
$scope.loginUser = function() {
$http.post('api/v1/login', $scope.userData)
.success((data) => {
$scope.userData = data.data;
window.localStorage.setItem('userData', angular.toJson(data));
window.localStorage.setItem('loggedIn', true);
$state.go('home');
})
.error((error) => {
console.log('Error: ' + error);
});
};
}
This being said, storing authenticated status in localStorage (or sessionStorage) is not a good path to go down. Both key/value pairs can be read in the developer pane and then altered (aka spoofed) via the console. A better solution is to return a unique value (GUID) after a successful login and store it in a cookie (set to expire in a short amount of time, like 20 minutes) that can be read on the server and verified there. You can and should use $cookie for this. Your user login state should be controlled server-side, never client-side. The client should always have to prove that it is authenticated.
To persist login, create a service that handles your visitor and let that service handle the login/logout and provide the proof of being logged in. That proof of being logged in should always be a private value that is held internally by the service and not accessible outside of it.
(function () {
'use strict';
var visitorModelService = ['$http', function ($http) {
var loggedIn = false,
visitorModel = {
login:function(){
//do login stuff with $http here
//set loggedIn to true upon success
},
loggedIn:function(){
return loggedIn;
},
logout:function(){
//do logout stuff with $http here
//no matter what, set loggedIn to false
}
};
return visitorModel;
}];
var module = angular.module('models.VisitorModel', []);
module.factory('VisitorModel', visitorModelService);
}());
Doing this, you can simply check for visitor.loggedIn in your ng-show and have everything centralized. Such as:
<a ng-click='visitor.logout' ng-show='visitor.loggedIn'>Log Out</a>
Better yet, put the elements that are only visible to authenticated users in a div tag and hide/show them en-mass.

how do I declare a $rootscope in a controller and access it in another controller

I am implementing an angular resource for a login system like this
..factory.js
//Create a factory for the Login API
angular.module(...)
.factory('LoginEntity', ['$resource', function ($resource) {
return $resource(
'API/sigin',
{
save: {method: 'POST'},
update: {method: 'PUT'}
}
);
}])
...controller.js
.controller('xxxController', ['LoginEntity', function(LoginEntity, $rootScope){
//in Controller add LoginEntity dependency
$rootScope.loggedinuser = {};
LoginEntity.save({
username: user.userName,
password: user.password
},
function (response) {
//success callback
$rootScope.loggedinuser = response;
},
function () {
//error callback
});
}]);
...AppCtrl
.controller('AppCtrl',function($scope,$rootScope){
username = $rootScope.loggedinuser.username;
}
That is what I have but the rootscope does not seem to be accesible in the App controller.
Any help, or assistance will be highly appreciated
your controller.js has a error, add the $rootScope to your code like this:
.controller('xxxController', ['LoginEntity', '$rootScope', function(LoginEntity, $rootScope){
//in Controller add LoginEntity dependency
$rootScope.loggedinuser = {};
LoginEntity.save({
username: user.userName,
password: user.password
},
function (response) {
//success callback
$rootScope.loggedinuser = response;
},
function () {
//error callback
});
}]);
Change your code to this:
.controller('xxxController', ['LoginEntity', '$rootScope', function(LoginEntity, $rootScope){
///
}]);
...AppCtrl
.controller('AppCtrl', ['$scope, '$rootScope', function($scope,$rootScope){
///
}]
use dependency injection. this should hopefully work:
.controller('AppCtrl',['$scope', '$rootScope', function($scope,$rootScope){
username = $rootScope.loggedinuser.username;
}])
This makes also sure that on minification, the behaviour does not break, wenn the variable names are automatically changed.
You have to inject $rootScope to your controller
.controller('xxxController', ['LoginEntity', '$rootScope', function(LoginEntity, $rootScope){
// TO DO Something
}]);
Or Implicit Annotation (careful to minify your code)
.controller('xxxController', function(LoginEntity, $rootScope){
// TO DO Something
});
Here is the link https://docs.angularjs.org/guide/di
inject $rootScope in controller
.controller('AppCtrl',['$scope', '$rootScope', function($scope,$rootScope){
$rootScope.loggedinuser = "your user detail"
}])
I'm not sure if this is what you wanted. If you want to persist the loggedinuser in localStorage, you should do it in success callback.
...AppCtrl
.controller('AppCtrl', ['LoginEntity', '$scope', '$rootScope', function(LoginEntity, $scope,$rootScope){
LoginEntity.save({
username: user.userName,
password: user.password
},
function (response) {
//success callback
localStorage.setItem('loggedinuser', JSON.stringify(response));
},
function () {
//error callback
LoggerService.error('Landing page:error during LoadTestEntity initiation');
});
}

Now I have error "ReferenceError: items is not defined" and cannot ideas how I can test my dataService.

I need help, about added jasmine tast to my factory.
My code is...
---dataService.js---
angular.module('angularAppApp')
.factory('dataService', function($resource){
return $resource(`http://...:3100/posts/:id`, null,
{
'update': { method:'PUT' }
});
})
---onePostCtrl.js ---
angular.module('angularAppApp')
.controller('onePostCtrl', ['$scope', '$http', '$routeParams', 'dataService',
function ($scope, $http, $routeParams, dataService) {
dataService.get ({id: $routeParams.postId}).$promise.then(function(data){
$scope.postInfo = data;
});
}]);
-- main container ---
angular.module('angularAppApp').controller('postCtrl', ['$scope','$http', 'ngDialog', 'dataService','trimService', function ($scope, $http, ngDialog, dataService, trimService) {
//save data to remote server from loaded pop-up
$scope.savePost = function(){
$scope.addFormData.date = $scope.formated_date;
dataService.save($scope.addFormData, function() {
laodData();
});
ngDialog.closeAll();
};
//delete post from remote server
$scope.deletePost = function(article) {
dataService.delete({ id: article._id }, function() {
laodData();
});
};
//edit post from remote server
$scope.updatePost = function (article) {
dataService.update({ id: article._id},article).$promise.then(function() {
laodData();
});
ngDialog.closeAll();
}
}]);
--- mock data ---
angular.module('mock', []).value('items', [{ ... }]
---At index.html I am have loaded mocks scripts---
src="bower_components/angular-mocks/angular-mocks.js"
src="mosk_data/mocks.module.js"
--Jasmine tests is ...
describe("factory of dataService", function (){
var $httpBackend, $http, $q, factory;
beforeEach(module("angularAppApp"));
beforeEach(module('mock'));
beforeEach(function(){
inject(function($injector, _$httpBackend_,_$http_,_$q_){
$q = _$q_;
$http = _$http_;
$httpBackend = _$httpBackend_;
$httpBackend.when('GET', '/items').respond(items);
factory = $injector.get('dataService');
});
afterEach(function () {
$httpBackend.verifyNoOutstandingExpectation();
$httpBackend.verifyNoOutstandingRequest();
});
it("Data service", function(){
});
});
Now, I have error "ReferenceError: items is not defined" and cannot ideas how I can test my dataService.
You forgot to inject your value and assign it to a variable in the tests. Try this:
var $httpBackend, $http, $q, factory, items; //declare variable items here (or you can do it inside beforeEach)
beforeEach(module("angularAppApp"));
beforeEach(module('mock'));
beforeEach(function(){
inject(function($injector, _$httpBackend_,_$http_,_$q_, _items_){
$q = _$q_;
$http = _$http_;
//inject the value and assign to your variable
items = _items_
$httpBackend = _$httpBackend_;
$httpBackend.when('GET', '/items').respond(items);
factory = $injector.get('dataService');
});
The Reference error you got was because there was no variable called items. You defined an angular value with name items, but it's not the same as a variable - think of it as it lives "somewhere inside angular guts" and to use it you have to inject it and then use as normal variable.

angular factory not available

angular.module('pipelineChromeApp', [
'ngResource',
'ngSanitize',
'ngRoute',
'LocalStorageModule'
])
angular.module('pipelineChromeApp')
.factory('Profile', [
'$http',
'apiUrl',
'localStorageService',
function ($http, apiUrl, localStorageService) {
var baseUrl = apiUrl + 'profile.json?api_key=';
return {
login: function(apiKey) {
return $http.get(baseUrl + apiKey);
},
logout: function() {
localStorageService.clearAll();
localStorageService.set('loggedIn', false);
console.log("cleared local storage");
return true;
}
}
}]);
angular.module('pipelineChromeApp')
.controller('LoginController', [
'$scope',
'Profile',
'$location',
function ($scope, Profile, $location) {
$scope.apiKey = "";
$scope.login = function(){
debugger
// Profile.login().then({
// $location.path( "/actions" );
// });
};
}]);
For some reason Profile isn't available in LoginController. Have I loaded things wrong?
As you mentioned in your comment, the problem you have is in the console, and I assume the browser you're using is chrome. In chrome/v8, the javascript engine tries very hard to optimize your code, it will remove any unused function parameters. In your case, Profile isn't used anywhere in your function, so v8 has removed it.
That's also the reason why it works fine when you have some code to do with the Profile.
Usually I will add a console.log() to an empty function if I want to check some variables in the chrome console, like this:
$scope.login = function() {
debugger;
console.log(Profile);
};

Categories

Resources