I'm currently trying to create some kind of modal dialog in AngularJS to Login a User. Therefore I created a small example using the template on the official ui-bootstrap page. To authentication the user, the credentials are sent to an REST-service. For sake of simplicity I used a dummy to simulate an http call. The received data should be passed back to the controller which called the modal dialog but somehow my prmisehandling doesn´t work and I recieve an error that the following code is wrong:
testLoginService.loginUser(user.name, user.pass)
.then(function (sessionId){
user.session = sessionId;
});
Here is the error that occurs in the console:
Error: testLoginService.loginUser(...) is undefined
$scope.ok#http://localhost:8080/LoginModal/example.js:32:2
Parser.prototype.functionCall/<#http://ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.js:10567:15
ngEventDirectives[directiveName]</<.compile/</</<#http://ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.js:18627:17
$RootScopeProvider/this.$get</Scope.prototype.$eval#http://ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.js:12412:16
$RootScopeProvider/this.$get</Scope.prototype.$apply#http://ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.js:12510:18
ngEventDirectives[directiveName]</<.compile/</<#http://ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.js:18626:15
createEventHandler/eventHandler/<#http://ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.js:2780:7
forEach#http://ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.js:330:11
createEventHandler/eventHandler#http://ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.js:2779:5
Here is my code on plunkr. What causes the error in my code and how to fix it? At the end I want to work with data received from the loginService and display the sessionID or other userspecific data on the user interface.
Thanks in advance
try the following,
use a callback function
testLoginService.loginUser(user.name, user.pass,function (data){
user.session = data.id;
});
the ajax request
this.loginUser = function(user, password,callback)
{
var wsUrl = "http://jsonplaceholder.typicode.com/posts";
var soapRequest = {
title: user,
body: password,
userId: 1
}
var config = {
headers : {
}
}
$http.post(wsUrl, soapRequest, config)
.success(callback)
.error(function (data, status, header, config) {
alert(req.responseText + " " + status);
})
};
demo: http://plnkr.co/edit/ucibA2X7s40BdxhOQ0K2?p=preview
Change your service call like this.
this.loginUser = function(user, password) {
var wsUrl = "http://jsonplaceholder.typicode.com/posts";
var soapRequest = {
title: user,
body: password,
userId: 1
};
var httpConfig = {
method: "POST",
url: wsUrl,
data: soapRequest
};
return $http(httpConfig);
};
Plunker: http://plnkr.co/edit/pjv9dTWso2fSawIygfSZ?p=preview
You need to add return to $http.post inside your service and handle success or error events in the controller:-
//service
this.loginUser = function(user, password)
{
var wsUrl = "http://jsonplaceholder.typicode.com/posts";
var soapRequest = {
title: user,
body: password,
userId: 1
}
var config = {
headers : {
}
}
return $http.post(wsUrl, soapRequest, config)
};
//controller
testLoginService.loginUser(user.name, user.pass)
.success(function (response){
user.session = response;
});
You were not returning any promise inside the loginUser method of the service
This is because you are not returning a promise. Try this :
this.loginUser = function(user, password)
{
var q = $q.defer();
var wsUrl = "http://jsonplaceholder.typicode.com/posts";
var soapRequest = {
title: user,
body: password,
userId: 1
}
var config = {
headers : {
}
}
$http.post(wsUrl, soapRequest, config)
.success(function (data, status, headers, config) {
q.resolve(data.id);
})
.error(function (data, status, header, config) {
alert(req.responseText + " " + status);
q.reject();
});
return q.promise;
};
Related
I have a service that returns a promise.
function GetSuggestedPeersService($http, SITE_CONFIG) {
var getSuggestedPeersService = this;
var data;
getSuggestedPeersService.getSuggestedPeersList = function() {
var baseUrl = SITE_CONFIG.baseUrl + "fetchSuggestedPeers";
var response = $http({
method : 'POST',
url : baseUrl,
headers : {
'Content-Type' : 'application/x-www-form-urlencoded'
},
data : data
});
return response;
}
getSuggestedPeersService.setSuggestedPeers = function(suggestedPeers) {
getSuggestedPeersService.suggestedPeers = suggestedPeers;
}
getSuggestedPeersService.getSuggestedPeers = function() {
return getSuggestedPeersService.suggestedPeers;
}
}
Now I use the following in the Controller to resolve the promise:
//gets the suggested peers
var promiseSuggestedPeers = GetSuggestedPeersService.getSuggestedPeersList();
promiseSuggestedPeers.then(function (response) {
peerHealthController.GetSuggPeersShow = response.data;
GetSuggestedPeersService.setSuggestedPeers(peerHealthController.GetSuggPeersShow);
return peerHealthController.GetSuggPeersShow;
})
.catch(function (error) {
console.log("Something went terribly wrong Suggested Peers.");
});
Now my question is call this service multiple times and need to update this on other service calls as well.
What is the best way to write the controller part so as not to repeat the resolve promise every time I call the service?
It's been long time.
But I just wanted to answer this question.
The best way to design this would be to use a factory. So this will become a reusable service.
An example code can be the following:
var httpMethods = peerHealthApp.factory('HttpService',HttpService);
httpMethods.$inject = ['$http', 'SITE_CONFIG'];
function HttpService($http, SITE_CONFIG){
console.log("SITE_CONFIG from Peer Service: " + SITE_CONFIG);
var factory = {
httpGet : function(relativePath,data){
var baseUrl = SITE_CONFIG.baseUrl + relativePath;
var response = $http({
method : 'GET',
url : baseUrl,
headers : {
'Content-Type' : 'application/x-www-form-urlencoded'
},
data : data
});
return response;
},
httpPost : function(relativePath, data){
var baseUrl = SITE_CONFIG.baseUrl + relativePath;
var response = $http({
method : 'POST',
url : baseUrl,
headers : {
'Content-Type' : 'application/x-www-form-urlencoded'
},
data : data
});
return response;
}
};
return factory;
}
And the above can be used again and again like the following:
var data=$.param({
"url":moderatedArticleLink
});
var promiseURLMetaData = HttpService.httpPost("parseUrlMetadata", data);
promiseURLMetaData.then(function (response) {
var urlMetaData = response.data;
return urlMetaData;
})
.catch(function (error) {
console.log("Something went terribly wrong while trying to get URL Meta Data.");
});
What is the best way to write the controller part so as not to repeat the resolve promise every time I call the service?
Instead of saving the data in a service, I recommend saving the promise:
if ( !Service.get() ) {
var promise = Service.fetch();
Service.set(promise);
});
Service.get().then(function (response) {
$scope.data = response.data;
}).catch( function(errorResponse) {
console.log(errorResponse.status);
throw errorResponse;
});
By checking for the promise and only fetching if necessary, multiple controllers can share the data without caring about the order of controller instantiation. This avoids race conditions and multiple XHRs to the same resource.
my question is: How can i pass variable(java script) to a rest apllication
This one of my functions in my controller.js:
This code sampel work, but i cant use my var email and password.
at the moment i use the url path log me in(url : 'rest/ab/einloggen/t#rt.de/22'). But how can i use var email(t#rt.de) and passwort(22).
app.controller('loginCtrl', function($scope, $location,$http){
$scope.submit = function(){
var email = $scope.username;
var password = $scope.password;
$http({
method : 'GET',
url : 'rest/ab/einloggen/t#rt.de/22'
}).success(function(data, status, headers, config) {
console.log(data);
if(data=="true"){
$location.path('/eingeloggt');
console.log("lalala");
}
}).error(function(data, status, headers, config) {
// called asynchronously if an error occurs
// or server returns response with an error status.
});
};
});
Here is the login rest function:
#Path("/einloggen/{username}/{passwort}")
#GET
public String einloggen(#PathParam("username") String Username,#PathParam("passwort") String Passwort)
{
// Bekomme die strings
Business b = new Business();
boolean test =b.einloggen(Username, Passwort);
//Return einer JSON
String ersatzBool ="false";
if(test==true){
ersatzBool="true";
}
return ersatzBool;
}
if you want to pass data to webapi you can use
'POST' instead of 'GET', In the below example I have passed json data {id: 2 }
and getting response as a list of products, In the api post method id 2 is available.
$http.post('http://localhost:1011/productDetails', { Id: 12 }, {
headers: {
'Content-MD5': '917200022538',
'Accept': 'application/Json',
'Content-Type': 'application/Json'
}
}).then(onUserComplete, onError);
var onUserComplete = function (response) {
$scope.Products = response.data;
};
var onError = function (reason) {
$scope.error = "Error while fetching records.";
};
This is something I had to do while communicating with a server(CMS application - Contentstack) using Restful api's, one striking difference would be I had to use authtoken.
$http({
url: siteUrl,
method: methode,
headers: {
access_token: auth_token,
api_key: site_api_key,
Accept: data_type, // --> 'application/json, text/plain, */*'
},
data: dataBody
}).then(function (resp) {
console.log('success ', resp);
callback(resp);
}, function(err){
console.log(err, "error");
});
I am trying the following code in an angular.js application to migrate data from one database to another. This is one part of the function in order to gain authorization credentials to send POSTs to the receiving database. However, it doesn't work. My first function, ATsintegrationsService.beginBackfill(clientIDs), returns the list of applicants fine. The error begins at getAuthToken(). Even though it hits the URL with the correct data, I keep on getting an error in the service. Can anyone shed some light on what is going on here, I'd really appreciate it. I'm at a loss for what may be causing my issues.
Main function (triggered by hitting an apply button):
$scope.beginBackfill = function() {
$scope.loading = true;
AtsintegrationsService.beginBackfill($scope.clientids).then(function (response) {
$scope.applicants = response.data;
$scope.getAuthToken();
$scope.createSuccess = true;
$scope.loading = false;
},
function(error) {
$scope.loading = false;
$scope.createFailure = true;
console.log("Failure to backfill data - " + error);
});
};
Here is $scope.getAuthToken():
$scope.getAuthToken = function() {
AtsintegrationsService.getAuthToken().then(function (response) {
$scope.authToken = response.data;
console.log($scope.authToken);
},
function(error) {
$scope.loading = false;
$scope.createFailure = true;
console.log("Failure to obtain auth token - " + error);
console.log(error);
});
};
And finally, the service code for getAuthToken() - some data has been removed and is indicated by {snip}.
srvc.getAuthToken = function () {
var url = {snip};
return $http({
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
responseType: 'json',
method: 'POST',
url: url,
data:
{
"grant_type": "{snip}",
"client_id": {snip},
"client_secret": "{snip}"
}
})
.success(function (data) {
console.log("We have a proper return.");
return data;
})
.error(function (data) {
console.log("There was an error in the service.");
return data;
});
};
We figured out the problem was with CORS headers; the code I have was fine.
I'm having troubles with $http calls in AngularJS. I've created the following services
crApp.service('authService', function ($http) {
var urlBase = 'http://192.168.xx.xx:8081';
// POST api/login/
this.login = function (credentials) {
return $http.post(urlBase + "/api/login", credentials);
};
// POST api/logout/
this.logout = function () {
return $http.post(urlBase + "/api/logout/", "");
};
}); //end service
crApp.service('dataService', function ($http) {
var urlBase = 'http://192.168.xx.xx:8081';
// POST api/query/
this.pull = function (query) {
return $http.post(urlBase + "/api/query", query);
};
From the controller I call the login method:
$scope.login = function(){
authService.login(credentials)
.success(function(data) {
console.log("RESULT LOGIN: " + data );
})
.error(function(data, status, headers, config) {
console.log(data);
console.log(status);
console.log(headers);
console.log(config);
});
};
So far so good and I receive a response where a cookie is set:
After succesfull login I call the following method:
var locations = { query: "from location select uid, name, description, address, phone", dataFormat: "verbose" };
$scope.getLocations = function() {
dataService.pull(portals)
.success(function (data) {
console.log("RESULT QUERY: " + data)
})
.error(function(data, status, headers, config) {
console.log("Query niet gelukt!");
console.log(data);
console.log(status);
console.log(headers);
console.log(config);
});
};
Result:
So cookie is not set in the headers.
I'm using AngularJS 1.3.15 and calls are made to a remote server on a different domain, but it does work in the REST Client tool in WebStorm (Jetbrains). So it must be something i'm missing in Angular!??
Hopefully someone can help me out.
You need to set withCredentials = true in the $http config to allow cookies to be set on CORS requests. This article explains more about cookies and CORS.
In your app config:
$httpProvider.defaults.withCredentials = true;
For example:
angular.module('myApp', [])
.config(['$httpProvider'){
$httpProvider.defaults.withCredentials = true;
}]);
You can read about this option in the $http provider documentation.
I've impelmented the httpInterceptor found here.
If my Basic Auth header has valid credentials, everything works fine, but if I get back a 401, then the application just hangs and I never receive a response.
Here's my interceptor:
angular.module('TDE').factory('httpInterceptor', function httpInterceptor ($q, $window, $location) {
return function (promise) {
var success = function (response) {
//window.logger.logIt("httpInterceptor received a good response: " + response);
return response;
};
var error = function (response) {
//window.logger.logIt("httpInterceptor received an error: " + response);
if (response.status === 401) {
$location.url('/login');
}
return $q.reject(response);
};
return promise.then(success, error);
};
});
Declaring the httpInterceptor in app.js
angular.module('TDE', []);
var TDE = angular.module('TDE', ['ux', 'ngRoute', 'ngResource', 'TDE', 'hmTouchEvents', 'infinite-scroll', 'ui.bootstrap', 'ui.sortable']);
TDE.config(['$routeProvider', '$locationProvider', '$httpProvider', function ($routeProvider, $locationProvider, $httpProvider) {
$httpProvider.responseInterceptors.push('httpInterceptor');
$routeProvider
.when('/', {})
.when('/login', { templateUrl: "Views/Login/login.html", controller: "LoginController" })
And my authenticate method
authenticate: function (user, password) {
// window.logger.logIt("serviceAccount: " + $rootScope.serviceAccount);
window.logger.logIt("In authenticate...");
var deferred = $q.defer();
var encoded = encoder.encode($rootScope.serviceAccount);
//var encoded = encoder.encode(user + ":" + password);
if (user && password) {
window.logger.logIt("We've got a username and password...");
$http.defaults.headers.common.Authorization = 'Basic ' + encoded;
sessionStorage.setItem('Authorization', $http.defaults.headers.common.Authorization);
var url = $rootScope.serviceBaseUrl + "login/authenticate";
window.logger.logIt(url);
$http({
method: "POST",
url: url,
data: {
"Username": user,
"Password": password,
"AccessToken": ""
},
headers: {
"Content-Type": "application/json"
}
})
.success(function (data, status, headers, config) {
window.logger.logIt("We've got a response (success)...");
if (data.IsAuthenticated) {
deferred.resolve(data);
session.setSession();
} else {
deferred.reject(status);
}
})
.error(function (data, status, headers, config) {
window.logger.logIt("We've got a response (error)...");
$dialogservice.showMessage("Authentication Error", "Return Code: " + status);
deferred.reject(status);
});
} else {
window.logger.logIt("We've got a response...");
deferred.reject(401);
}
return deferred.promise;
},
You'll see that in my Authenticate method, there are two lines that I'm testing:
var encoded = encoder.encode($rootScope.serviceAccount);
and
var encoded = encoder.encode(user + ":" + password);
We are REQUIRED to use Basic Authentication (which is over SSL). Right now, all I'm testing is that I can receive a 401 back. If I use the $rootScope.serviceAccount (which is working), I get a 200 response right away. But if I purposely send a bad username/password, I NEVER get a response, the application just sits there.
Edit: Ok, I've updated my code to the following, and still getting the same behavior:
angular
.module('TDE')
.config(['$httpProvider', function ($httpProvider) {
$httpProvider.interceptors.push(function ($q) {
return {
'request': function (config) {
window.logger.logIt("Request is being sent...");
var headers = config.headers;
if (!headers.Authorization) {
headers.Authorization = sessionStorage.getItem('Authorization');
}
return config || $q.when(config);
},
'response': function (response) {
window.logger.logIt("got a good response...");
return response;
},
'responseError': function (rejection) {
window.logger.logIt("responseError error...");
return $q.reject(rejection);
},
};
});
}]);
Well, again, PhoneGap is the issue!!!!!!!!!!!!!!!!!
Example 1
Example 2
Example 3
Example 4
Try this interceptor:
.factory('httpInterceptor', function(){
return {
request : function(yourRequestConfig){
var returnPromise = $q.defer();
$http(yourRequestConfig).then(function(response) {
console.log("successful response from server ", response);
returnPromise.resolve(response);
}, function(someReason) {
console.log("failure response from server", reason);
returnPromise.reject(reason);
});
return returnPromise.promise;
}
}
});
used as
httpInterceptor.request(request config).then(returnValue){
console.log('inside controller', returnValue);
});
where request config is something like:
var requestConfig = {
method: "GET",
url: "localhost:8080/getStuff"
};