Angularjs Factoryname.function is not a function - angularjs

I am trying to call a factory function from the controller .
My code:
angular.module("mainApp", ['ui.router', 'ngAnimate', 'toaster'])
.factory("authenticationSvc", function($http, $q, $window) {
var userInfo;
function login(userName, password) {
var deferred = $q.defer();
$http.post("/api/login", {
userName: userName,
password: password
}).then(function(result) {
userInfo = {
accessToken: result.data.access_token,
userName: result.data.userName
};
$window.sessionStorage["userInfo"] = JSON.stringify(userInfo);
deferred.resolve(userInfo);
}, function(error) {
deferred.reject(error);
});
return deferred.promise;
}
return {
login: login
};
})
.controller("LoginController", function($scope, toaster, $rootScope, $stateParams, $location, $http, authenticationSvc) {
$scope.login = authenticationSvc.login();
});
But I am getting an error
TypeError: authenticationSvc.login is not a function

The function login needs two parameter
So the function login without a parameter isn't definded

Firstly, the approach and formalization of factory is not done properly.
try using the following approach..
.factory("authenticationSvc", function($http, $q, $window) {
var userInfo;
var authenticationSvc={};
//Define login()
authenticationSvc.login=function(userName, password) {
var deferred = $q.defer();
$http.post("/api/login", {
userName: userName,
password: password
}).then(function(result) {
userInfo = {
accessToken: result.data.access_token,
userName: result.data.userName
};
$window.sessionStorage["userInfo"] = JSON.stringify(userInfo);
deferred.resolve(userInfo);
}, function(error) {
deferred.reject(error);
});
return deferred.promise;
}
//return Factory Object
return authenticationSvc;
})
And in the controller , try calling in the same approach
.controller("LoginController", function($scope, toaster, $rootScope, $stateParams, $location, $http, authenticationSvc) {
$scope.login = authenticationSvc.login();
});
Hope this helps.
Cheers

Here below is the basic example that how factories are behaving. Please change your code with below one
angular.module("mainApp", ['ui.router', 'ngAnimate', 'toaster'])
.factory("authenticationSvc", function($http, $q, $window) {
var userInfo, authentication = {};
authentication.login = function(userName, password) {
var deferred = $q.defer();
$http.post("/api/login", {
userName: userName,
password: password
}).then(function(result) {
userInfo = {
accessToken: result.data.access_token,
userName: result.data.userName
};
$window.sessionStorage["userInfo"] = JSON.stringify(userInfo);
deferred.resolve(userInfo);
}, function(error) {
deferred.reject(error);
});
return deferred.promise;
}
return authentication;
})
.controller("LoginController", function($scope, toaster, $rootScope, $stateParams, $location, $http, authenticationSvc) {
$scope.login = authenticationSvc.login(user,password);
});
Please check though I didn't test it. Inside in your factory :
You just create an object, add properties to it, then return that same
object. When you pass this service into your controller, those
properties on the object will now be available in that controller
through your factory.

Related

How to use angular services with controllers

I'm new to angular and I've been told that it's better to make services do the heavy lifting for the controllers, but I'm finding it diffcult to make use of the services I've created. I've seen several questions on this but I can't find solutions.
Here's my service
(function () {
'use strict';
var office = angular.module('Office', []);
office.factory('auth', ['$http', '$localForage', '$scope', function ($http, $localForage, $scope) {
var auth = {}
auth.login = function (credentials) {
$http.post('/auth_api/login', credentials)
.then(function (data) {
$localForage.setItem('user', data.data)
},
function () {
$scope.login_error = 'Invalid Username/password'
})
}
$localForage.getItem('user').then(function (data) {
auth.isAuthenticated = !!data.id
})
return auth
}])
And here's my controller
office.controller('LoginController', ['$scope', 'auth', function ($scope, auth) {
$scope.login = auth.login($scope.user)
}])
I have created a simpler version from your code.. and its working here . check the link - fiddle
app.factory('auth', ['$http', function ($http) {
var auth = {};
auth.login = function (credentials) {
return "success";
}
return auth;
}]);
replace login function with your implemenation
Your code is correct but as you are not returning anything from the "auth" factory, you are not getting any update in the controller. Change your code as shown below to return the data from factory or any message acknowledging the login.
Factory :
(function () {
'use strict';
var office = angular.module('Office', []);
office.factory('auth', ['$http', '$localForage', '$scope', function ($http, $localForage, $scope) {
var auth = {}
auth.login = function (credentials) {
return $http.post('/auth_api/login', credentials)
.then(function (data) {
$localForage.setItem('user', data.data);
setAuthentication(true);
return data.data;
},
function (err) {
return err;
});
}
auth.setAuthentication = function (isLoggedIn){
this.isAuthenticated = isLoggedIn;
}
return auth;
}]);
Controller :
office.controller('LoginController', ['$scope', 'auth', function ($scope, auth) {
$scope.login = function (){
auth.login($scope.user).then(function (data){
$scope.userDetails = data;
}, function (err){
$scope.loginError = 'Invalid Username/password';
});
}
}]);

stuck in Error: [$injector:unpr] Unknown provider

Basically, I want to do a user authentication before login. Thus, i create a authentication factory and user login controller to achieve my goal. However, A Error is thrown when a factory is injected into a controller. I have no idea where cause this error in my program. Can anyone give me a hint?
My facotry:
(function () {
'use strict';
angular
.module('app')
.factory('AuthenticationService', AuthenticationService);
AuthenticationService.$inject = ['$http', '$cookieStore', '$rootScope', '$timeout', 'UserService'];
function AuthenticationService($http, $cookieStore, $rootScope, $timeout, UserService) {
var service = {};
service.Login = Login;
service.SetCredentials = SetCredentials;
service.ClearCredentials = ClearCredentials;
return service;
function Login(username, password, callback) {
$http.post('/api/authenticate', { username: username, password: password })
.success(function (response) {
// actually calling SetCredentials in logincontroller
callback(response);
});
}
function SetCredentials(username, password) {
var authdata = Base64.encode(username + ':' + password);
$rootScope.globals = {
currentUser: {
username: username,
authdata: authdata
}
};
$http.defaults.headers.common['Authorization'] = 'Basic ' + authdata; // jshint ignore:line
$cookieStore.put('globals', $rootScope.globals);
}
function ClearCredentials() {
$rootScope.globals = {};
$cookieStore.remove('globals');
$http.defaults.headers.common.Authorization = 'Basic';
}
}
// Base64 encoding service used by AuthenticationService
var Base64 = {
// encode and decode
// ignore detail this time
}
})();
My controller:
(function () {
'use strict';
angular
.module('app')
.controller('LoginController', LoginController);
LoginController.$inject = ['$location', 'AuthenticationService'];
function LoginController($location, AuthenticationService) {
var vm = this;
vm.login = login;
(function initController() {
// reset login status
AuthenticationService.ClearCredentials();
})();
function login() {
vm.dataLoading = true;
AuthenticationService.Login(vm.username, vm.password, function (response) {
if (response) {
AuthenticationService.SetCredentials(vm.username, vm.password);
$location.path('/');
} else {
console.log('Fail to log in');
vm.dataLoading = false;
}
});
};
}
})();

Can't access service in controller

So I'm trying to retrieve a token from the server but I'm encountering an error when trying to call a method in my service.
LoginController.js:
(function(){
angular.module('app')
.controller('LoginController', [
'$http', 'authService',
LoginController
]);
function LoginController(authService ) {
var vm = this;
vm.user = {};
vm.login = function () {
console.log("logging in");
authService.getToken("admin", "admin")
.then(function (data) {
console.log(data);
}, function (error) {
//TODO: error handling
})
};
}
})();
authService.js:
(function(){
'use strict';
angular
.module('app')
.factory('authService', ['$http', '$rootScope', 'REST_END_POINT',
authService
]);
function authService($http, $rootScope, REST_END_POINT){
return {
getToken: function(username, password) {
var config = {
headers: {
'Accept': 'application/json'
}
};
var data = {
username: login,
password: password
};
return $http.post(REST_END_POINT, +"/authenticate", data, config);
}
};
}
})();
I keep getting this error :
TypeError: authService.getToken is not a function
at LoginController.vm.login
You forgot to add $http to your controller function.
angular.module('app')
.controller('LoginController', [
'$http', 'authService',
LoginController
]);
function LoginController(_$http_needs_to_be_here, authService ) {
...
Remove $http from this line since you have it injected in your service already
angular.module('app')
.controller('LoginController', [
'authService',
LoginController
]);
You have wrong no of params in LoginController function. You have request angular to inject $http and authService. But you have only one param in function. For more info pls read Angular DI
Re-write code:
(function(){
angular.module('app')
.controller('LoginController', [
'$http', 'authService',
LoginController
]);
function LoginController($http, authService ) {
var vm = this;
vm.user = {};
vm.login = function () {
console.log("logging in");
authService.getToken("admin", "admin")
.then(function (data) {
console.log(data);
}, function (error) {
//TODO: error handling
})
};
}
})();

Promise returning object in angular js

i have my authservice as given below ,
myApp.factory('Authentication',
['$rootScope', '$location', 'URL', '$http', '$q',
function ($rootScope, $location, URL, $http, $q) {
var myObject = {
authwithpwd: function (user) {
var dfd = $q.defer();
$http
.post('Mart2/users/login', {email: user.email, password: user.password})
.then(function (res) {
return dfd.resolve(res.data);
}, function (err) {
return dfd.reject(err.data);
});
return dfd.promise;
} //login
};
return myObject;
}]); //factory
And i'm using that service in user service as follows :
myApp.factory('UserService',
['$rootScope', '$location', 'URL', '$http', '$q', 'Authentication',
function ($rootScope, $location, URL, $http, $q, $Authentication) {
var myObject = {
login: function (user) {
$Authentication.authwithpwd(user).then(function (regUser) {
console.log(regUser);
}).catch(function (error) {
$rootScope.message = error.message;
});
},
getUserToken: function () {
return $rootScope.currentUser.apiKey;
},
isLogged: function () {
if ($rootScope.currentUser) {
return true;
} else {
return false;
}
}
//login
};
return myObject;
}]); //factory
I am very new to angular js . While writing service and calling that service from controller i have put a console debug in user service which is showing its returning object .i am getting object if i do console.log(regUser) ? any idea why ?
To get the object you need to do change your myObject declaration. Basically you need to return a promise from the login function and then write a callback to get the resolved data.
myApp.factory('UserService',
['$rootScope', '$location', 'URL','$http','$q','Authentication',
function($rootScope,$location, URL,$http,$q,$Authentication) {
var myObject = {
login: function(user) {
var defer = $q.defer();
$Authentication.authwithpwd(user).then(function(regUser) {
console.log(regUser);
defer.resolve(regUser);
}).catch(function(error) {
$rootScope.message = error.message;
defer.reject(regUser);
});
return defer.promise;
},
getUserToken:function() {
return $rootScope.currentUser.apiKey;
},
isLogged:function() {
if($rootScope.currentUser){
return true;
} else {
return false;
}
}//login
};
return myObject;
}]); //factory
To extract the object from controller or from some other service you need to write a callback
UserService.login(user)
.then(function (data) {
$scope.data = data;
}, function (error) {
$scope.error = error;
});
Also in the Authentication service you can just do a 'dfd.resolve' instead of 'return dfd.resolve'; since you are already returning the dfd.promise.
I have created a fiddler here

Pass authentication error from factory to controller in AngularJS

I am trying to implement Firebase authentication via a factory and I would like to pass the error and even the authData object back to the controller from the factory. Is this possible? I can't seem to figure out how. I keep getting undefined variables.
If I print the error upon a failed login to console.log I get what should be expected, so the rest of this code works. I just can't pass the error/obj back to the controller.
My controller:
myApp.controller('LoginController', ['$scope', '$location', 'Authentication', function($scope, $location, Authentication) {
$scope.login = function() {
Authentication.login($scope.user);
// do something with error from auth factory
}
}]);
My factory:
myApp.factory('Authentication', ['$firebase', 'FIREBASE_URL', '$location', function($firebase, FIREBASE_URL, $location){
var ref = new Firebase(FIREBASE_URL);
var authObj = {
login: function(user) {
return ref.authWithPassword({
email : user.email,
password : user.password
}, function(error, authData) {
if (error) {
// pass error back to controller
// i've tried the following:
// authObj.err = error;
// return authObj.err = error;
}
else {
// pass authData back to controller
}
});
} // login
};
return authObj;
}]);
You simply pass an error handler function to the factory from the controller. Something like this (untested):
//Controller
myApp.controller('LoginController', ['$scope', '$location', 'Authentication', function($scope, $location, Authentication) {
$scope.login = function() {
Authentication.login($scope.user, function(error, authData) {
// access to error
});
}
}]);
//Factory
myApp.factory('Authentication', ['$firebase', 'FIREBASE_URL', '$location', function($firebase, FIREBASE_URL, $location){
var ref = new Firebase(FIREBASE_URL);
var authObj = {
login: function(user, errorHandler) {
return ref.authWithPassword({
email : user.email,
password : user.password
}, errorHandler);
} // login
};
return authObj;
}]);
Maybe you can do this in your controller:
$scope.login = function() {
Authentication.login(username, password).then(
function(result) {
$location.path('/stuff');
},
function(result) {
$scope.showLoginErrorMessage = true;
});
};
Note that then() takes 2 functions as parameters (one for success and one for error). This does depend on how your Authentication service works, but it looks OK to me.

Resources