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
})
};
}
})();
Related
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';
});
}
}]);
got this error "Error: [$injector:cdep] Circular dependency found: $cookies <- $cookies <- AuthService"
with following code
'use strict';
angular.
module('core.auth').
factory('AuthService', [ '$http', '$rootScope', 'ConfigService', '$cookies',
function AuthService($http, $rootScope, ConfigService, $cookies) {
const service = {};
service.Login = Login;
service.SetCredentials = SetCredentials;
service.ClearCredentials = ClearCredentials;
return service;
function Login(username, password, callback) {
$http.post(ConfigService.LOGIN_API, { username: username, password: password })
.success(function (response) {
callback(response);
});
}
function SetCredentials(username) {
$rootScope.globals = {
currentUser: {
username: username
}
};
$cookies.put('globals', $rootScope.globals);
}
function ClearCredentials() {
$rootScope.globals = {};
$cookies.remove('globals');
}
}
]);
and i'm use this service in login component
'use strict';
angular.
module('login').
component('login', {
templateUrl: 'dist/components/login/login.template.html',
controller: ['$location', 'AuthService', '$log',
function LoginController($location, AuthService, $log) {
(function initController() {
// reset login status
AuthService.ClearCredentials();
}());
this.login = () => {
AuthService.Login(this.username, this.password, (response) => {
if (response.success) {
$log.log(response);
$log.log('Login successful', true);
AuthService.SetCredentials(this.username);
$location.path('#!/products');
} else {
$log.log(response)
}
})
}
}
],
controllerAs: 'vm'
});
can't understand whats wrong with my code... If remove $cookies from here, it's working perfectly. Maybe solution is write own cookies service? :)
A circular dependency is always the sign of mixing of concerns, which is a really bad thing.One of the authors of AngularJS, explains a nice solution on his awesome blog. In short, you probably have a third service hidden somewhere, which is the only part of your code really needed by the two others.
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.
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
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.