I have a main.js javascript file that has an init() function in.
I also have this AngularJS service:
(function () {
var app = angular.module('spContact', ['ngRoute']);
app.factory('spAuthService', function ($http, $q) {
var authenticate = function (userId, password, url) {
var signInurl = 'https://' + url + '/_forms/default.aspx?wa=wsignin1.0';
var deferred = $q.defer();
var message = getSAMLRequest(userId, password, signInurl);
$http({
method: 'POST',
url: 'https://login.microsoftonline.com/extSTS.srf',
data: message,
headers: {
'Content-Type': "text/xml; charset=\"utf-8\""
}
}).success(function (data) {
getBearerToken(data, signInurl).then(function (data) {
deferred.resolve(data);
}, function (data) {
deferred.reject(data)
})
});
return deferred.promise;
};
return {
authenticate: authenticate
};
function getSAMLRequest(userID, password, url) {
return 'envelope';
}
function getBearerToken(result, url) {
var deferred = $q.defer();
var securityToken = $($.parseXML(result)).find("BinarySecurityToken").text();
if (securityToken.length == 0) {
deferred.reject();
}
else {
$http({
method: 'POST',
url: url,
data: securityToken,
headers: {
Accept: "application/json;odata=verbose"
}
}).success(function (data) {
deferred.resolve(data);
}).error(function () {
deferred.reject();
});
}
return deferred.promise;
}
});
})();
How can I call this services "authenticate" method from the init() function of my main JavaScript file?
This service should return some authentication cookies that I would need for data querying.
You need to inject this factory to some controller/directive like:
app.controller('MyCtrl', ['spAuthService', function (spAuthService) {
spAuthService.authenticate.then(function (data) {
// ...
});
}]);
And this controller MyCtrl may be put on some home page and bootstrapped by Angular automatically.
Related
I have a config.prop file which is being called from ngConfig.js file which is a service file. This prop file contains an URL which I need in my 2nd service file ngContent.js .
These files are being called individually from resolve.
$routeProvider.
when('/login', {
templateUrl: 'views/login.html',
controller: LoginController,
resolve: {
urlData: function(Config) {
return Config.prop().then(function(response) {
return response;
});
},
contentData:function(Content){
return Content.prop().then(function(response){
return response;
});
}
}
})
The response I am getting from urlData, which is resolving my response from ngConfig.js is the content of the config.prop. I need this response in my ngContent.js file.
The content of ngConfig.js is
angular.module('ngConfig', [])
.service('Config', function ($http, $rootScope, $document) {
//API calling method for all method
this.prop = function () {
try {
//API calling
var promise = $http({
method: 'GET',
dataType: "application/json",
data: 'json',
cache: false,
url: 'config.prop',
}).then(function (response) {
return response;
}, function (response) {
return response;
});
} catch (ex) {
return ex;
}
return promise;
};
});
The content of ngContent.js is
angular.module('ngContent', [])
.service('Content', function ($http, $rootScope, $document) {
//API calling method for all method
this.prop = function () {
try {
//API calling
var promise = $http({
method: 'GET',
dataType: "application/json",
data: 'json',
cache: false,
url: API_URL
}).then(function (response) {
return response;
}, function (response) {
return response;
});
} catch (ex) {
return ex;
}
return promise;
};
});
The API_URL is present in config.prop file, which is called from ngConfig.js file.
I hope I was able to present my problem clearly.
Thanks in advance.
You may pass urlData to contentData, like this, and then pass it to Content.prop().
contentData: function(Content, urlData){
return Content.prop(urlData).then(function(response){
return response;
});
}
Edit
This doesn't work with $routeProvider, you have to use $stateProvider of ui-router.
I have used it and it works. Use it the same way as discussed above.
I have this service that loads data..
angular.module('App').service('daysService', ['$http','$q',function($http,$q) {
var days = [];
return {
loadDay: function() {
$http({
method: 'get',
url: '/app/days/list/',
}).success(function(data) {
days.push(data);
return days;
}).error(function (data) {
console.log('Error checking server.');
});
}
};
}]);
than in the controller i call the service
daysService.loadDay.then(function(data) {
alert(data)
});
But i'm getting this error TypeError: daysService.loadDay.then is not a function
Any suggestion?
You are not returning anything from your loadDay function. Try this:
return {
loadDay: function() {
return $http({ // <-- return the promise
method: 'get',
url: '/app/days/list/',
}).success(function(data) {
days.push(data);
return days;
}).error(function (data) {
console.log('Error checking server.');
});
}
};
daysService.loadDay.then(function(data) {
alert(data)
});
On the first line you are not calling loadDay like a function you are accessing it as a property. so you need to change it to this:
daysService.loadDay().then(function(data) {
alert(data)
});
Note the parenthesis on loadDay.
Secondly, you are using a service like a factory. So you have two options:
angular.module('App').service('daysService', ['$http','$q',function($http,$q) {
var days = [];
this.loadDay = function() {
$http({
method: 'get',
url: '/app/days/list/',
}).success(function(data) {
days.push(data);
return days;
}).error(function (data) {
console.log('Error checking server.');
});
};
}]);
OR
angular.module('App').factory('daysService', ['$http','$q',function($http,$q) {
var days = [];
return {
loadDay: function() {
$http({
method: 'get',
url: '/app/days/list/',
}).success(function(data) {
days.push(data);
return days;
}).error(function (data) {
console.log('Error checking server.');
});
}
};
}]);
Finally, you aren't returning the promise from the function:
function() {
return $http({
method: 'get',
url: '/app/days/list/',
}).success(function(data) {
days.push(data);
return days;
}).error(function(data) {
console.log('Error checking server.');
});
};
And if I were doing this, I would do:
angular.module('App').factory('daysService', ['$http', '$q', function($http, $q) {
var days = [];
this.loadDay = function() {
return $http.get('/app/days/list/').then(
function(data) {
days.push(data);
return days;
},
function(data) {
console.log('Error checking server.');
}
);
};
}]);
Your factory should return a promise instead of days if you want to use .then(). I believe you can do something like return $q.when(days) instead of return days and that should work.
Also just to note, .success() and .failure() callbacks are deprecated as of Angular 1.4. Not sure which version you're using, but $http now uses .then following this pattern:
$http({stuff}).then(function successCallback(response) {
//success
}, function errorCallback(response) {
// error
});
angular.module('App').service('daysService', ['$http','$q',function($http,$q) {
var days = [];
return {
loadDay: function() {
$http({
method: 'get',
url: '/app/days/list/',
}).success(function(data) {
days.push(data);
//return days;
}).error(function (data) {
console.log('Error checking server.');
});
},getDays: function(){ return days; }
};
}]);
daysService.loadDay(); $window.alert(daysService.getDays());
If you create a promise only then will you be able to use it with .then(). Check this document on how to create a promise. It is simple. https://docs.angularjs.org/api/ng/service/$q
You code is right now incapable of using .then() and the object/object property is not present so the error TypeError: daysService.loadDay.then is not a function. Else write a code that does not require you to use .then() but can work as normally triggered functions. That will work too.
/* In your service */
angular.module('App').factory('daysService', ['$http',function($http) {
var days = [];
return {
loadDay: function() {
$http({
method: 'get',
url: '/app/days/list/',
}).success(function(data) {
days.push(data);
return days;
}).error(function (data) {
console.log('Error checking server.');
return;
});
}
};
}]);
/* In your controller trigger the eventorclick */
$scope.trigger = function(){
$scope.modelname = daysService.loadDay(); /* returns days else undefined or null */
alert($scope.modelname); /* handle your issues if you have array of objects */
}
I want to write a function in AngularJS that returns a value (actually it is a string). That value is returned by a http request, but async is driving me crazy.
My first attempt was:
this.readParameter = function(key) {
$http({
method: "GET",
url: "XXXXXXX",
headers: { 'Content-Type': 'application/json' }
}).then(function successCallback(response) {
return response.data;
}, function errorCallback(response) {
throw new Error("Error");
})
};
But of course it does not work because of Angular async features (response.data is undefined)
What is the way to do it? I just want to return the value (string), so I can use this function like
var a = readParameter("key1")
What you can do is define some variable with initial value outside function and on response set value inside success function instead of returning it.
Delegator pattern works great here to assign $http task to some service and use callback method for response.
Controller (Call Service for specific request) -> Service (Manage request params and other things and return factory response to Controller) -> Factory (Send request and return it to Service)
Basic example of Callback
var myVariable = '';
function myFunction (key, callback) {
$http({
method: "GET",
url: "XXXXXXX",
headers: { 'Content-Type': 'application/json' }
}).then(function successCallback(response) {
callback(response);
}, function errorCallback(response) {
throw new Error("Error");
})
};
function myCallbackFunction(response) {
myVariable = response.data; // assign value to variable
// Do some work after getting response
}
myFunction('MY_KEY', myCallbackFunction);
This is basic example to set value but instead use callback pattern from above example.
var myvariable = '';
function myFunction (key) {
$http({
method: "GET",
url: "XXXXXXX",
headers: { 'Content-Type': 'application/json' }
}).then(function successCallback(response) {
myvariable = response.data; // set data to myvariable
// Do something else on success response
}, function errorCallback(response) {
throw new Error("Error");
})
};
myFunction('MY_KEY');
Don't try to mix async and sync programming. Instead use a callback to use like
readParameter("key1", callback)
for example:
this.readParameter = function(key, callback) {
$http({
method: "GET",
url: "XXXXXXX",
headers: { 'Content-Type': 'application/json' }
}).then(function successCallback(response) {
callback(response)
}, function errorCallback(response) {
throw new Error("Error");
})
};
I resolve this by using promise:
Example :
in Service (invoicesAPIservice => invoicesapiservice.js) you use:
angular.module('app')
.service('invoicesAPIservice', function ($http) {
this.connectToAPI= function () {
return new Promise(function(resolve,reject){
var options = {
method:'GET',
url :'',
headers:{
'X-User-Agent': '....',
'Authorization': '....',
}
};
$http(options).then(function successCallback(response) {
resolve(response);
//console.log(response);
},function errorCallback(response) {
reject(response);
})
});
});
});
and in your Controller (mainCtrl=> mainCtrl.js):
angular.module('app').controller('mainCtrl', function($scope,invoicesAPIservice) {
$scope.connectToAPI=function () {
invoicesAPIservice.connectToAPI().then(function (content) {
console.log(content.statusText);
}.catch(function (err) {
//console.log(err);
alert("Server is Out");
});
}
});
And in your page : index.html:
<button ng-click="connectToAPI()"></button>
:)
I'm trying to build an angular service I can reuse for doing my http requests etc. This all works when it's not in a service.
The following code works and does the login, but the log of $scope.data is always undefined. If i put a log in on the success before I return data it returns the data, but not back to the controller which is what i'm really looking to do.
Just for clarification, I want to be able to access the json data returned from the server as 'data' in the success in my controller.
//App.js
.service('SaveSubmitService', function ($http, $log) {
this.addItem = function(url, options){
var xsrf = $.param({
Username: options.Username,
Password: options.Password
});
$http({
method: 'POST',
url: url,
data: xsrf,
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
}).success(function(data, status, headers, config) {
return data;
}).
error(function(data, status, headers, config) {
console.log(data);
return false;
});
}
})
Controller:
.controller('LoginCtrl', function ($scope, $stateParams, $location, $ionicLoading, $http, SaveSubmitService, $log) {
if (localStorage.getItem("SessionKey")) {
$location.path('home');
}
$scope.login = {};
$scope.doLogin = function doLogin() {
$scope.data = SaveSubmitService.addItem('http://*****/Services/Account.asmx/Login', $scope.login);
$log.info($scope.data);
};
})
First of all make SaveSubmitService return promise object. Then use its API to provide a callback to be executed once data is loaded:
.service('SaveSubmitService', function ($http, $log) {
this.addItem = function (url, options) {
var xsrf = $.param({
Username: options.Username,
Password: options.Password
});
return $http({
method: 'POST',
url: url,
data: xsrf,
headers: {'Content-Type': 'application/x-www-form-urlencoded'}
})
.then(function(response) {
return response.data;
})
.catch(function(error) {
$log.error('ERROR:', error);
throw error;
});
}
});
And the you will use it like this in controller:
$scope.doLogin = function doLogin() {
SaveSubmitService.addItem('http://*****/Services/Account.asmx/Login', $scope.login).then(function(data) {
$scope.data = data;
$log.info($scope.data);
});
};
Note, how you return result of $http function call, it returns Promise which you use in controller.
saveSubmitService Service method is returning promise and it can be resolved using .then(function())
Your controller code will look like below.
CODE
$scope.doLogin = function doLogin() {
var promise = saveSubmitService.addItem('http://*****/Services/Account.asmx/Login', $scope.login);
promise.then(function(data) {
$scope.data = data
});
};
Thanks
.factory('SaveSubmitService', function ($http, $log) {
return{
getData:function(url,xsrf)
{
$http({
method: 'POST',
url: url,
data: xsrf,
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
}).success(function(data, status, headers, config) {
return data;
}).
error(function(data, status, headers, config) {
console.log(data);
return false;
});
}
}
})
.controller('LoginCtrl', function ($scope, $stateParams, $location, $ionicLoading, $http, SaveSubmitService, $log) {
if (localStorage.getItem("SessionKey")) {
$location.path('home');
}
$scope.login = {};
$scope.doLogin = function doLogin() {
$scope.data = SaveSubmitService.addItem(, );
$log.info($scope.data);
};
SaveSubmitService.getData('http://*****/Services/Account.asmx/Login',$scope.login).success(function(data,status){
$scope.data
}).error(function(data,status){ });
)};
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"
};