I am learning AngularJS and have the structure of the project set up but when i call the API that returns me JSON i can't display that in the html.
The idea is you click on the button and the returned result will be displayed in {{answer}}.
HTML:
<div ng-app="xileapp">
<div ng-controller="searchController">
<input type="button" ng-click="search()" value="search" />
<div>Answer: {{answer}}</div>
</div>
</div>
Controller:
xile.controller('searchController', ['personSearch', '$scope', function (personSearch, $scope) {
$scope.search = function () {
$scope.answer = personSearch.findPlayer();
}
}]);
Service:
xile.service('personSearch', function ($http) {
this.findPlayer = function() {
$http({
method: 'GET',
url: 'https://euw.api.pvp.net/api/lol/euw/v1.4/summoner/by-name/Crucify?api_key=222015c4-0898-4f6b-a7d5-2a23c3e0344d'
}).then(function successCallback(response) {
// this callback will be called asynchronously
// when the response is available
return response;
}, function errorCallback(response) {
// called asynchronously if an error occurs
// or server returns response with an error status.
return response;
});
};
});
The URL is hitting success with the correct response. How do I now get the data to display in the HTML.
Angular has a Json filter you can add to the actual binding expression, once you have the json back.
{{ answer | json }}
If you want the actual json from the response, you can find it in the data property of the response object.
response.data
Improvement suggestion:
I've also provided a 'nicer' short hand for your http get method which I think its actually better because it'll handle any exceptions that gets thrown rather than using an error callback in your case.
return $http.get(apiUrl)
.then(successCB)
.catch(errorCB);
You are not assigning any data to the answer (actually assigning undefined) because findPlayer doesn't return anything.
So first of all, you need to make service method return promise object:
this.findPlayer = function() {
var url = 'https://euw.api.pvp.net/api/lol/euw/v1.4/summoner/by-name/Crucify?api_key=222015c4-0898-4f6b-a7d5-2a23c3e0344d';
return $http({
method: 'GET',
url: url
}).then(function successCallback(response) {
// this callback will be called asynchronously
// when the response is available
return response.data;
}, function errorCallback(response) {
// called asynchronously if an error occurs
// or server returns response with an error status.
return response;
});
};
then consume it in controller:
$scope.search = function () {
personSearch.findPlayer().then(function(data) {
$scope.answer = data;
});
}
Please log this JSON object and figure out proporty you want display
{answer: "a"}
then
your view will be as
<div>Answer: {{answer.answer}}</div>
and return data from findPlayer function or promise
Related
I know that many similar issues had been discussed here but not a single answer helped me with my specific issue. I have a function and I perform a $http get request inside it. I also pass a object as an argument in the function. On a successful response I see the correct data and I try to assign it to the outside variable that I'm passing. But data from the response doesn't seem to "escape" outside the function. The outside variable is also a scope variable. I don't use it directly because the function is supposed to be used by other controllers down the hierarchy.
Here's the function:
$scope.getUser = function (userID, userData) {
var response = $http({
method: "GET",
url: ("user/" + userID),
responseType: "json"
})
.then(
function (response) { //success
return response.data;
},
function (response) { //error
alert(response.data.message);
return undefined;
})
.then(function (data) {
userData = data;
});
};
Basically I'm trying to assign the result to userData like this:
$scope.user = {} //in the beginning of the controller.
//.....
$scope.getUser(1, $scope.user);
and after that $scope.user is still untouched.
I also tried putting that inside $apply function but the result was still the same.
If I put $scope.user inside the function instead of the userData argument everything is ok but like I said, it's not the purpose of the function. It should be capable of working with any variable. I'm using angular ui router and the controller in which this function is located is on the top of the hierarchy and all other controllers should access it and use it to obtain a user from the database.
The approach mentioned in your question isn't a valid one and I would suggest you to wait for the results in your controller function to make any $scope assignments.
Give it a try
$scope.getUser = function (userID) {
return $http({
method: "GET",
url: ("user/" + userID),
responseType: "json"
}).then(function (results) {
return results.data;
});;
}
//and call it from your controller like
$scope.getUser(1).then(function (data){
//perform any data validations here
$scope.user = data;
});
Modifying input parameter of a function would not guarantee that it also updates function's caller, and it is not a good programming pattern.
You may consider passing an update delegate to the function which contains the logic of updating the data you need. For example, here is a revised getUser function
$scope.getUser = function (userID, updateUserDataDelegate) {
var response = $http({
method: "GET",
url: ("user/" + userID),
responseType: "json"
}).then(
function (response) { //success
updateUserDataDelegate(response.data);
},
function (response) { //error
alert(response.data.message);
return undefined;
}
);
};
$scope.user = {} //in the beginning of the controller.
var updateScopeUserDelegate = function( userData ) { $scope.user = userData; };
$scope.getUser(1, updateScopeUserDelegate);
I am trying to submit a form data to an API endpoint which I created. I have tested it in PostMan and the API functions well and I can get the data in successfully. But while connecting that API endpoint to a function in angular js I get the following error.
Heres my code:
$scope.saveSession = function() {
$http.post("/session/survey", $scope.session).success(function(data, status) {
$window.location.href = '/';
console.log("Sucessfully getting data" + JSON.stringify(data));
})
}
Note:
$scope.session is an object that being populated by using the ng-model tag.
For example:
<input type="text" ng-model="session.title">
Edit (Controller Code):
// This is our controller for the bio page
var session = angular.module('session', ['sessionService'])
session.controller('sessionCtrl', function($scope, $http, $window, sessionServices) {
$scope.session = {};
$scope.saveSession = function() {
$scope.session.sessionNo = 1;
$scope.session.coach = "mmmm";
$scope.session.modules = "wokr place";
//console.log(user);
$http.post("/session/survey", $scope.session).success(function(data, status) {
$window.location.href = '/';
console.log("Sucessfully getting added bio" + JSON.stringify(data));
})
};
});
That's because .success() really isn't a function. As the documentation explains, a promise is returned by $http.post() which you can chain with .then()
$http.post('/someUrl', data, config).then(successCallback, errorCallback);
Use promises, "success" function doesn't exists in $http object($http success and error methods are available only in older versions of Angular 1.x, but they've removed in Angular 1.6):
// Simple GET request example:
$http({
method: 'GET',
url: '/someUrl'
}).then(function successCallback(response) {
// this callback will be called asynchronously
// when the response is available
}, function errorCallback(response) {
// called asynchronously if an error occurs
// or server returns response with an error status.
});
More in official documentation https://docs.angularjs.org/api/ng/service/$http
It's because you're using $http.post().success.
Try;
$scope.saveSession = function() {
$http.post("/session/survey", $scope.session).then(function(data, status) {
$window.location.href = '/';
console.log("Sucessfully getting data" + JSON.stringify(data));
})
}
We use .then to return a "promise" from the $http service.
Hope it helps!
I just dealt with a similar issue with versions 1.7.2 and 1.7.4. It's not exactly the same issue because I was never using .success but I'm posting here because this post comes up first when searching.
When using the shortcut version $http.post(/api/endpoint/', data) I would get:
"TypeError: $http.post is not a function"
And if I used it with the callbacks exactly as it appears in the documentation:
$http({method: 'POST', url: '/api/endpoint/', data: $scope.newObject}).then(function (response) {
$scope.status = response.status;
$scope.data = response.data;
}, function (response) {
$scope.data = response.data || 'Request failed';
$scope.status = response.status;
});
I was getting
"TypeError: $http(...).then is not a function"
In this case the problem was that I had both $resource and $http in the same controller. Not sure if this is the intended behavior but removing $resource suddenly made $http work again.
Hopefully this helps someone else
I'm new to AngularJS.
I'm calling a service from a controller that is communicating with a webservice. the service returns a promise to the controller. Now I want to apply the data that is available on the success function of the promise to $scope. How can I achieve this? I already tried to do $scope.$apply() on the service call or the promise success function, but this just gives me errors.
Controller:
angular.module('home')
.controller('HomeCtrl',
['$scope', 'myService',
function ($scope, myService) {
$scope.data = [];
$scope.getData = function () {
// this is triggered via btn click
myService.getSomeData(reqData)
.then(
function success(res){
// apply res.data to $scope.data ?
},
function failure(err){
//error handling
}
);
}
}]);
Service:
angular.module('myService')
.factory('myService', ['$http', '$rootScope',
function ($http, $rootScope) {
return {
generalWebServiceProxy: function (webserviceName, data, xml) {
// do some xml stuff, settings header etc
return $http({
method: 'POST',
url: URL,
headers: headers,
data: data
});
},
getSomeData: function (data) {
return this.generalWebServiceProxy('WSName', data, true).then(/* do something here and return data*/);
}
}
}]);
Thanks in advance!
$http returns a promise where the server response is resolved. That response object contains things like status, data, header, etc.. etc...
Your service should handle these responses itself. So that the method setSomeData resolves to that data. Right now, it's resolving to the server response which isn't very useful for your directive.
generalWebServiceProxy: function (webserviceName, data, xml) {
// this method is return a promise
return $http({...});
},
// this method uses "promise chaining"
getSomeData: function (data) {
return this.generalWebServiceProxy(
'WSName',
data,
true).then(function(response) {
if(response.status == 200) {
return response.data;
}
throw new Error("Unexpected response:"+response.status);
});
}
In the above code I've done something called promise chaining. That's where the return value of a then mutates the resolve value. So the next promise then call will have response.data as the parameter.
Later in your directive you can use the promise returned by the service as a regular promise. It just resolves to the data in the response.
$scope.getData = function () {
myService.getSomeData(reqData)
.then(function success(data) {
// ^^ data is actually the value `response.data` from the service
});
}
What about error handling?
There are two kinds of errors with $http. There are HTTP errors like unable to resolve host, failure to connect or timeouts, and then there are response errors. Such as content missing or content not found. Some of these can be handled with the promise failure callback, and some are successful responses that you don't want.
So in my example I restrict success to mean an HTTP 200 response. You might want to check that the data given back is what you were expecting (for example, is it an array?).
I've found it better to handle errors using a HTTP interceptor. Otherwise you have to implement error handles in every directive that uses the service.
$http is a promise and over here you not returning the promise and using it as a promise in the controller.
Modified Service:
angular.module('myService')
.factory('myService', ['$http', '$rootScope',
function ($http, $rootScope) {
return {
generalWebServiceProxy: function (webserviceName, data, xml) {
// do some xml stuff, settings header etc
return $http({
method: 'POST',
url: URL,
headers: headers,
data: data
});
},
getSomeData: function (data) {
return this.generalWebServiceProxy('WSName', data, true);
}
}
}]);
And have the controller as is and update the $scope variable within success block.
In the promise then function when you receive the data object it is wrapped with another data object like
data = Object {data: Object, status: 200, config: Object, statusText: "OK"}
How to avoid this. you need to access your variables like data.data.myVar
var test123 = $scope.test();
test123.then(function(data){
console.log(data);
// why you need to access your data in "data.data.myValue"
},function(data){
});
$scope.test = function(){
var promise = $http(
{
method: 'GET',
dataType: "jsonp",
url: 'json/requestKey.json'
}
)
.success(function(data) {
return data;
})
.error(function(data){
//return data;
});
return promise;
};
Just return the data part from your "service". And you can ditch the redundant promise since $http is already a promise.
$scope.test().then(function(data) {
console.log(data);
});
$scope.test = function() {
return $http('json/requestKey.json').then(function(response) {
return response.data;
});
};
Well this is be resolved two ways
Try returning the resulting object instead of wrapping it around another object and then returning that to the client on the server side.
In the success() callback of your $http, return data.data instead of just return data, so that in your then() function you will get the internal object.
When you are returning, HttpResponseMessage, REST api response data in this format,
Object {data: Object, status: 200, config: Object, statusText: "OK"}
To parse in ajax success call back,
$http.get(urlBase + '/get/' + id).then(function (response) {
var yourData = response['data'];
var yourStatusCode = response['status'];
var yourStatusText = response['statusText'];
//assign data to any other $scope object
$scope.product = yourData;
}, function (error) {
console.log('error occured!!');
});
You will do fine now, you don't need to change the response from web api now.
I know that the data is coming from the server (I have unit tests and have seen the data in the debugger in chrome) but I can't figure out how to return the data from the angular service to the angular controller.
Service:
UPDATED
surchargeIndex.service('customerService', [
'$http', function ($http) {
this.getTest = function () {
return $http({
method: "GET",
url: "api/Customer/GetTest",
})
.success(function(data) {
return data;
});
};
}
]);
Controller:
surchargeIndex.controller('SurchargeIndexController', function ($scope, customerService, templateService) {
$scope.customers = customerService.getTest();
});
Data has the array from the server so the array is populated in the service. So to reiterate the data is there; however, I receive a 404 error INSIDE of the success handler during debugging.
What am I missing?
$http works asynchronously; fortunately it returns a promise which will be fulfilled when the response retrieved from the server. So you should return $http's get method and use returned promise to handle data.
this.getTest = function () {
return $http({
method: "GET",
url: "api/Customer/GetTest",
})
.success(function(data) {
return data;
})
.error(function() {
alert("failed");
}); // This returns a promise
};
Then in your controller you should use that promise to retrieve the expected data.
surchargeIndex.controller('SurchargeIndexController', function ($scope, customerService, templateService) {
//Use the returned promise to handle data, first parameter of the promise is used for successful result, if error happens, second parameter of the promise returns the error and you can do your error handling in that function
customerService.getTest().then(function(customers){$scope.customers = customers;}, function(err){console.error(err);})
});
You need to define a Callback to get your data "back" to your controller, after an async http call... There are different ways to do... I will show you one way without a callback, or a promise, but the best way would be to use a callback, or promise...
Wild West Way:
app.controller('myCTRL', function($scope, myService) {
$scope.valueWanted = myService.valueWanted;
myService.getData();
});
app.service('myService', function($http) {
var myThis = this;
this.valueWanted = "";
this.getData = function () {
$http.get('api/Customer/GetTest').success(function (data) {
myThis.valueWanted = data.valueWanted;
});
};
});