I have an issue on my application when I get an API request from members belongs to a particulary group.
GET /api/organizations/1234/members?group=4321
If I start my navigation with this request, I have the right members but if I navigate in other page with other groupe before, the $http response is full of parasite members whereas the response form API is right (check from network tab in Chrome developper tools).
I think about some cache but I can not find it ! For info, I use jsData for mounting my data but it's not seems to be the problem.
Here the code of my function to send Api Request :
var loadGroupMembers = function() {
return $q(function(resolve, reject) {
var callParams = {
organizationId: $stateParams.OrganizationId,
groupId: $stateParams.groupId
};
sendApiCall('groupMembers', 'get', callParams)
.success(function(data) {
resolve(data);
})
.error(function(data) {
});
});
};
var sendApiCall = function(requestId, method, params, data, queryStringParams) {
params = params || {};
data = data || {};
var apiCallConfig = {
params: config.params,
method: config.method,
url: "/api/organizations/1234/members?group=4321",
data: data,
cache : false
};
$rootScope.fn.setHistory($state.current.name, 'apiCall', 'sendManualApiCall:' + requestId);
return $http(apiCallConfig);
};
Please tell me if you have questions or need more details.
Thanks for your help ! :)
Edit : I add the function that call sendApiCall and I made a little apiary to show you how the data from api are : http://private-52326-groupmember.apiary-mock.com/organization/1234/members?group=4321
It was kind of link with Jsdata and an interceptor created by an other developer. For each api request, the interceptor add some data on the response with the same type ... So the issue is closed.
Thanks for your help anyway :)
Related
I am an angular novice and am working on an app that gets data from an accounting software and visualises different things using google charts.
Since the api of the accounting software doesn't give me the data the way I need it I have to process it before passing it to the google charts api.
No the problem I ran into is that I can't access the data that is returned inside of the http get request function due to scope I guess. I have tried quite a few things, but nothing seems to work. I feel like there should be an obvious solution to this, but can't put my finger on it.
Would be great if someone can help me with a method to expose http request data to make it usable outside of the http function itself.
Here is a code example:
myApp.controller("dataFetch", ['$http', '$scope',function($http, $scope){
var self = this;
self.project = {};
self.TSproject;
self.TShours;
//PASSING AUTHORIZATION
var config = { headers: { 'Authorization': 'Bearer 1lFASlwgM3QwSyZfJVJPO6776X5wlZtogdg8RN-Lt',} };
//GET DATA
$http.get('https://api.freeagent.com/v2/projects/941562', config).then(function(response) {
//SAVING PROJECT DATA
self.project = {
name: response.data.project.name,
url: response.data.project.url
};
return self.project.url;
}, function(errResponse) {
console.error("Get project request failed");
}).then(function(pUrl) {
return
$http.get('https://api.freeagent.com/v2/timeslips?' + 'from_date=2015-09-21&to_date=2015-09-28' + 'user=' + pUrl, config).then(function(response) {
self.TSproject = response.data.timeslips[0].project;
self.TShours = response.data.timeslips[0].hours;
});
});
//GOOGLE CHARTS
$scope.data1 = {};
$scope.data1.dataTable = new google.visualization.DataTable();
$scope.data1.dataTable.addColumn("string","User")
$scope.data1.dataTable.addColumn("number","Qty")
//INSERTING DATA FROM SERVER HERE
$scope.data1.dataTable.addRow([self.TSproject, self.TShours]);
$scope.data1.title="Daniels Timeslips";
}]);
Thanks a lot!
The problem with your code is that you're trying to initialize your charts even before your GET call is complete.
Even though it looks like $http.get() comes first in your code, it's an Asynchronous operation, so JS interpreter will not wait for that call to complete. It will simply fire the AJAX call using $http.get() and continue with the remaining statements in code i.e Google Charts initialization in your case.
When the response is available, we have promises to be invoked after completion of your AJAX call and that is where you're ideally supposed to initialize your charts as they're dependent on that AJAX call response.
Having said that, you can make this work by simply moving your charts initialization to the callback of your second GET request like below.
$http.get('https://api.freeagent.com/v2/projects/941562', config).then(function(response) {
// removing your code for brewity
}, function(errResponse) {
console.error("Get project request failed");
}).then(function(pUrl) {
$http.get('https://api.freeagent.com/v2/timeslips?' + 'from_date=2015-09-21&to_date=2015-09-28' + 'user=' + pUrl, config).then(function(response) {
self.TSproject = response.data.timeslips[0].project;
self.TShours = response.data.timeslips[0].hours;
//GOOGLE CHARTS
$scope.data1 = {};
$scope.data1.dataTable = new google.visualization.DataTable();
$scope.data1.dataTable.addColumn("string","User")
$scope.data1.dataTable.addColumn("number","Qty")
//INSERTING DATA FROM SERVER HERE
$scope.data1.dataTable.addRow([self.TSproject, self.TShours]);
$scope.data1.title="Daniels Timeslips";
});
});
I think you should create the google chart object inside the last http promise.
//GET DATA
$http.get('https://api.freeagent.com/v2/projects/941562', config).then(function(response) {
//SAVING PROJECT DATA
self.project = {
name: response.data.project.name,
url: response.data.project.url
};
return self.project.url;
}, function(errResponse) {
console.error("Get project request failed");
}).then(function(pUrl) {
return
$http.get('https://api.freeagent.com/v2/timeslips?' + 'from_date=2015-09-21&to_date=2015-09-28' + 'user=' + pUrl, config).then(function(response) {
self.TSproject = response.data.timeslips[0].project;
self.TShours = response.data.timeslips[0].hours;
//GOOGLE CHARTS
$scope.data1 = {};
$scope.data1.dataTable = new google.visualization.DataTable();
$scope.data1.dataTable.addColumn("string","User")
$scope.data1.dataTable.addColumn("number","Qty")
//INSERTING DATA FROM SERVER HERE
$scope.data1.dataTable.addRow([self.TSproject, self.TShours]);
$scope.data1.title="Daniels Timeslips";
});
});
Now you should be able to access in your template {{ data1 }} with all the info.
I am trying to use the Forecast.io weather API to build a weather application with Ionic. I am having a hell of a time getting the AJAX response data delivered to my controller for use in my view.
My Factory Service:
.factory('WeatherService', function($cordovaGeolocation) {
var posOptions = { timeout: 10000, enableHighAccuracy: false };
return {
// Get current Geolocation position with the configured /posOptions/
getPosition : $cordovaGeolocation.getCurrentPosition(posOptions),
// Query the result of /getPosition/ for /lat/, /long/, and /accuracy/
getCoords : function(pos) {
var loc = {
lat : pos.coords.latitude,
long : pos.coords.longitude,
accuracy : pos.coords.accuracy
};
return loc;
},
// Build the API request URI
getApi : function(lat, long) {
var url = 'https://api.forecast.io/forecast/';
var apiKey = 'foo';
var forecastApi = url + apiKey + '/' + lat + ',' + long + '?callback=?';
return forecastApi;
},
// Execute a request against the API URI to recieve forecast data
getForecast : function(api) {
var forecast;
$.ajax({
url : api,
dataType : 'json',
async : false,
success : function(res) {
forecast = res;
}
});
return forecast;
}
};
})
My Controller Method:
.controller('DashCtrl', function($scope, WeatherService) {
WeatherService.getPosition.then(function(pos) {
var pos = pos;
return pos;
}).then(function(pos) {
var coords = WeatherService.getCoords(pos);
return coords;
}).then(function(coords) {
var api = WeatherService.getApi(coords.lat, coords.long);
return api;
}).then(function(api) {
$scope.forecast = WeatherService.getForecast(api);
console.log($scope.forecast);
});
})
There's probably a lot of things inherently wrong with the above code. From my reading I have been made aware that then() methods really shouldn't be used in the controller method, and all of that logic should be isolated to the Service Method. I will be refactoring to that pattern when I get this working.
I am using the jQuery $.ajax() instead of $http because of CORS issues with Forecast.io when developing locally. $jsonp was throwing syntax errors on the response, so I had to resort to jQuery for the call to get this working locally.
I know I am getting a successful response because if I console.log(forecast) inside the $.ajax call I can explore the weather data. For whatever reason, I am unable to save the response value to the forecast var saved in the parent scope of the ajax call and then return that to the controller for use in my view with the $scope.forecast variable. It is always returning undefined.
I have looked at plenty of SO questions while trying to get this working on my own, and have yet to have any success..
How do I return the response from an asynchronous call?
Get Data from a callback and save it to a variable in AngularJS
Well, if you really really feel the need to use ajax (probably better to track down and fix the jsonp issue) then you should probably wrap the forcast in your very own promise.
.factory('WeatherService', function($q,$cordovaGeolocation) {
...
getForecast : function(api)
{
var deferred = $q.defer();
$.ajax({url : api, dataType : 'json', async : false,
success : function(res) {
defereed.resolve(res);
}
});
return defereed.promise;
}
You already know how to handle promises in your controller code so I won't post those changes.
I'm developing a single page application. I am making use of Angularjs.v1.2.28. I'm making a HTTP GET request to the backend using this code.
return {
getCategories : function(sessionid,terminalid,tableno,section){
var req = {
method: 'GET',
url: Config.url+ "/menucategories",
params : {
'sessionid' : sessionid,
'terminalid' : terminalid,
'tableno' : tableno,
'section' : section
}
};
return $http.get(req);
},
I make use of the promise object that is returned from service in controller.
var categoryPromise = categoryService.getCategories(sessionid,terminalid,tableno,section);
categoryPromise.then(function(payload){
var categories = payload.data;
if(categories.status.code == "1"){
if(Object.prototype.toString.call(categories) === '[object Array]') {
$scope.categories = categories;
categoryService.setCategories(categories);
$scope.pax = tableService.getPax();
$scope.tablechair = tableService.getChoseTableChair();
}
}
else{
$location.url("/login");
$scope.errorMsg = categories.status.desc;
}
},function(errorPayload){
$location.url("/login");
$scope.errorMsg = "Server error while processing the request.Please contact system administrator";
});
It's always the errorCallback is getting called due to the URL getting changed to the browser application URL appended with some malformed characters. The URL which i give is
http://localhost:8080/CafexRestful/menucategories
But, it gets changed to the browser application URL below
http://localhost:8080/CafexMobile/[object%20Object]
I have been debugging in Chrome and Firebug. I couldn't resolve it. It may be something which is happening under the hood. The same code is working with another controller and service, where i fetch a different data. Please let me know if you need anymore information. Thanks.
$http.get in angularjs needs an url string. You should use url string instead of an object
Using $http.get function:
return {
getCategories : function(){
return $http.get("/menucategories"); // using $http.get function.
},
Using $http function.
return {
getCategories : function(sessionid,terminalid,tableno,section){
var req = {
method: 'GET',
url: Config.url+ "/menucategories",
params : {
'sessionid' : sessionid,
'terminalid' : terminalid,
'tableno' : tableno,
'section' : section
}
};
return $http(req); //using $http function only.
},
Please see the document: https://docs.angularjs.org/api/ng/service/$http
I can't see what the problem with this is.
I'm trying to fetch data on a different server, the url within the collection is correct but returns a 404 error. When trying to fetch the data the error function is triggered and no data is returned. The php script that returns the data works and gives me the output as expected. Can anyone see what's wrong with my code?
Thanks in advance :)
// function within view to fetch data
fetchData: function()
{
console.log('fetchData')
// Assign scope.
var $this = this;
// Set the colletion.
this.collection = new BookmarkCollection();
console.log(this.collection)
// Call server to get data.
this.collection.fetch(
{
cache: false,
success: function(collection, response)
{
console.log(collection)
// If there are no errors.
if (!collection.errors)
{
// Set JSON of collection to global variable.
app.userBookmarks = collection.toJSON();
// $this.loaded=true;
// Call function to render view.
$this.render();
}
// END if.
},
error: function(collection, response)
{
console.log('fetchData error')
console.log(collection)
console.log(response)
}
});
},
// end of function
Model and collection:
BookmarkModel = Backbone.Model.extend(
{
idAttribute: 'lineNavRef'
});
BookmarkCollection = Backbone.Collection.extend(
{
model: BookmarkModel,
//urlRoot: 'data/getBookmarks.php',
urlRoot: 'http://' + app.Domain + ':' + app.serverPort + '/data/getBookmarks.php?fromCrm=true',
url: function()
{
console.log(this.urlRoot)
return this.urlRoot;
},
parse: function (data, xhr)
{
console.log(data)
// Default error status.
this.errors = false;
if (data.responseCode < 1 || data.errorCode < 1)
{
this.errors = true;
}
return data;
}
});
You can make the requests using JSONP (read about here: http://en.wikipedia.org/wiki/JSONP).
To achive it using Backbone, simply do this:
var collection = new MyCollection();
collection.fetch({ dataType: 'jsonp' });
You backend must ready to do this. The server will receive a callback name generated by jQuery, passed on the query string. So the server must respond:
name_of_callback_fuction_generated({ YOUR DATA HERE });
Hope I've helped.
This is a cross domain request - no can do. Will need to use a local script and use curl to access the one on the other domain.
I've been stuck on this one for a while. I'm trying to use OAuthSimple.js to interact with Twitter in a Chrome extension I've written.
The signing process seems to work fine for requests to retrieve a user's statuses, but I can't seem to construct a request that will successfully authenticate when I try to retweet, reply, or mark a tweet as favorite.
I'm following the guides here. I have also tried numerous ways of structuring the request, and comparing the request contents against the output of the OAuth tool provided by Twitter ( which seems to check out ), but I'm still getting 401 errors and generic "We couldn't authenticate you" responses.
Here's how I'm trying to form the request:
var sendTwitterRequest = function(url, params, method, callback) {
var request = null;
if ( localStorage.twitterAuthToken ) {
OAuthSimple().reset();
request = OAuthSimple(TwitterConsumerKey,TwitterConsumerSecret).sign({
action:method,
method:"HMAC-SHA1",
dataType:"JSON",
path:url,
parameters:params,
signatures:{
oauth_version:'1.0',
oauth_token:localStorage.twitterAuthToken,
oauth_secret:localStorage.twitterAuthVerifier
}
});
console.log(request);
$j.ajax({
url:request.signed_url,
type:method,
data:request.parameters,
success:callback
});
}
};
Then, making calls into this method like this:
// this works, I get the data and can do stuff with it
sendTwitterRequest('http://api.twitter.com/1/statuses/user_timeline.json?user_id=',null,'GET',someMethod());
// this fails and throws a 401 error every time
sendTwitterRequest("https://api.twitter.com/1/statuses/retweet/"+tweetKey+".json",null,'POST',someOtherMethod());
Am I missing something? Thanks in advance!
It turns out the requests I am creating are fine, I just needed a final one to exchange request tokens for OAuth tokens. I thought this step was covered when the user was prompted for input, but turns out I was wrong.
I also ended up switching from OAuthSimple.js to just OAuth.js, on account of the fact that I could only get OAuth.js to process both the token requests and the timeline requests.
Some of this is pretty specific to what my application is doing, so you will probably need to modify it.
The new sendTwitterRequest method:
var sendTwitterRequest = function(options){
var accessor={
consumerSecret:TwitterConsumerSecret
};
var message={
action:options.url,
method:options.method||"GET",
parameters:[
["oauth_consumer_key",TwitterConsumerKey],
["oauth_signature_method","HMAC-SHA1"],
["oauth_version","1.0"]
]
};
if(options.token){
message.parameters.push(["oauth_token",options.token])
}
if(options.tokenSecret){
accessor.tokenSecret=options.tokenSecret
}
for(var a in options.parameters) {
message.parameters.push(options.parameters[a])
}
OAuth.setTimestampAndNonce(message);
OAuth.SignatureMethod.sign(message,accessor);
try {
$j.ajax({
url:message.action,
async:options.async||true,
type:message.method||'GET',
data:OAuth.getParameterMap(message.parameters),
dataType:options.format||'JSON',
success:function(data) {
if (options.success) {options.success(data);}
}
});
} catch ( e ) {
}
};
And the methods that depend on it:
// asks Twitter for an oauth request token. User authorizes and the request token is provided
requestTwitterToken = function() {
// this is semi-specific to what my extension is doing, your callback string may need
// to be slightly different.
var callbackString = window.top.location + "?t=" + Date.now();
var params = [
[ 'oauth_callback', callbackString ]
];
sendTwitterRequest({
url: "https://api.twitter.com/oauth/request_token",
method: 'POST',
parameters: params,
format: 'TEXT',
success: function(data) {
var returnedParams = getCallbackParams(data);
if ( returnedParams.oauth_token ) {
chrome.tabs.create({
url:"https://api.twitter.com/oauth/authorize?oauth_token=" + returnedParams.oauth_token
});
}
},error:function( e ) {
console.log( 'error' );
console.log( e );
}
});
};
// exchanges the Twitter request token for an actual access token.
signIntoTwitter = function(token, secret, callback) {
var auth_url = "https://api.twitter.com/oauth/access_token";
var authCallback = function(data) {
var tokens = getCallbackParams(data);
localStorage.twitterAuthToken = tokens.oauth_token || null;
localStorage.twitterAuthTokenSecret = tokens.oauth_token_secret || null;
callback();
};
try {
sendTwitterRequest({url:auth_url, method:'POST', async:true, format:'TEXT', token:token, tokenSecret:secret, success:authCallback});
} catch ( e ) {
console.log(e);
}
};
With this, the steps are as follows:
ask Twitter for a token ( requestTwitterToken() ) and provide a callback
in the callback, check to see if a token is provided. If so, it's an initial token
pass the token back to Twitter and open the Twitter auth page, which allows the user to grant access
in the callback to this call, see if an access token was provided
exchange the request token for an access token ( signIntoTwitter() )
After that, I simply use the sendTwitterRequest() method to hit Twitter's API to fetch the timeline and post Tweets.