Angular js not waiting for $http ? - javascript

This is my first angular js application. I am trying to make an http request and get back response.
app.service('info',['$http',function($http){
var details=function (query) {
$http({
method:'GET',
url:'http://api.openweathermap.org/data/2.5/forecast/daily',
params:{q:query,cnt:8}
}).then(function (response){
console.log(response.data);
return response.data;
},function (response){
console.log('s');
});
};
return {details:details}
}]);
And this is my controller:
app.controller("search",['$scope','$routeParams','info',function($scope,$routeParams,info){
if ($routeParams.param) {
var d=info.details($routeParams.param);
d.then(function (r){
console.log("success");
},function (e){
console.log("fail");
});
}]);
But on using the it shows "Cannot read property 'then' of undefined".I have read solutions to similar problems here and this was a working solution in many problems, but I don`t get where its going horribly wrong.
Also do explain this statement :
return {details:details}

In your details function, you need to return $http().
var details=function (query) {
return $http(...);
};

Related

$http.post is not a function

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

How to get value from $http function in angularjs

I've create a function in angular. And it is working fine and can get correct result but my problem is i want particular node from result. i have worked with JSON and Jquery, but i am new in angular.
This is my code.
$scope.booking= function(docid,addid){
//console.log(addid);
var a = $http({
method: 'POST',
url: "http://localhost:81/DoctorStayServiceAngular/model/getDoctorBookingDetail.php",
params:{"doctorid":docid,"addressid":addid,"day":weekday[d.getDay()]}
//params:{"doctorid":docid}
}).then(function mySucces(response) {
//$scope.count= response.data;
/*$scope.appo=[];
$scope.appo= i;
i++;*/
//
//console.clear();
return response.data;
});
console.log(a);
return a;
};
http://localhost:81/DoctorStayServiceAngular/model/getDoctorBookingDetail.php
return following json.
{
"status":"success",
"message":"",
"booking":{
"booking_detail":[{
"session":null,
"slot":null,
"day":"Friday"
}]
}
}
This how i can see in firebug
Expanded view
so i want to get value(which I've highlighted in image) from response(which is under $$state), what should i do?
in short how can i get bottom result?
{
"status":"success",
"message":"",
"booking":{
"booking_detail": [{
"session":null,
"slot":null,
"day":"Friday"
}]
}
}
$http service returns a promise(this is printed in your console logs), which will be resolved after that http call is complete.
Please go through this $q documentation on how deferred data works.
https://docs.angularjs.org/api/ng/service/$q
This should work,
$scope.booking= function(docid,addid){
$http({
method: 'POST',
url: "http://localhost:81/DoctorStayServiceAngular/model/getDoctorBookingDetail.php",
params:{"doctorid":docid,"addressid":addid,"day":weekday[d.getDay()]}
//params:{"doctorid":docid}
}).then(function mySucces(response) {
$scope.responseData = response.data;
});
};
After this you can bind the data in responseData to your view.

AngularJS http call (complete syntax)

I'm new to AngularJS and
I needed to know if we can make a jQuery like Ajax call in Angular and wanted to know it's complete syntax,
if anyone could help me making the whole code syntax.
Example in jQuery I could do something like -
$.ajax(
{
url: 'someURL',
type: 'POST',
async: false,
data:
{
something: something,
somethingelse: somethingelse
},
beforeSend: function()
{
$('#someID').addClass('spinner');
},
success: function(response)
{
$('#someID').removeClass('spinner');
console.log(response);
},
complete: function(response)
{
$('#someID').removeClass('spinner');
console.log(response);
},
error: function (errorResp)
{
console.log(errorResp);
}
});
Now here's what I found out on making http call in Angular,
Need help in building the complete syntax, with all possible options -
var req = {
method: 'POST',
url: 'someURL',
headers: {
'Content-Type': undefined
},
data: {
//goes in the Payload, if I'm not wrong
something: 'something'
},
params:{
//goes as Query Params
something: 'something',
somethingElse: 'somethingElse'
}
}
$http(req)
.then(function()
{
//success function
},
function()
{
//Error function
});
now what if I want to attach a spinner on some id in the BeforeSend function like in jQuery and remove the spinner in success,
What is the Angular's way as a like to like for BeforeSend or making the http call async?
Angular even let you control this better :). Two ways can be chosen here:
1. Wrapping $http
You can write for each request with by using a wrapper of $http which will add some methods before and after you made request
app.factory('httpService',function($http){
function beginRequest() {};
function afterRequest() {};
return {
makeRequest: function(requestConfig){
beginRequest();
return $http(requestConfig).then(function(result){
afterRequest(result);
});
}
}
})
Then each time you can call this function to make a request. This is not new.
2. Using interceptor
Angular has a better way to handle for all request. It use a new concept named 'interceptor'. You write your interceptor as a normal service and push one or many interceptors into $http service and depend on type of interceptor, it will be called each time your request happen. Look at this picture to think about interceptor:
Some common task for interceptor can be: Add/remove a loading icon, add some more decorator to your http config such as token key, validate request, validate responded data, recover some request...
Here is example of a interceptor that add a token key into headers of a request
app.service('APIInterceptor', function($rootScope, UserService) {
var service = this;
service.request = function(config) {
var currentUser = UserService.getCurrentUser(),
access_token = currentUser ? currentUser.access_token : null;
if (access_token) {
config.headers.authorization = access_token;
}
return config;
};
service.responseError = function(response) {
return response;
};
})
Then add interceptor to your $http:
app.config(['$httpProvider', function($httpProvider) {
$httpProvider.interceptors.push('APIInterceptor');
}]);
Now all request will be added a token key to header. cool right?
See here for more information:
there is eveyrthing here to help with your question :https://docs.angularjs.org/api/ng/service/$q http://chariotsolutions.com/blog/post/angularjs-corner-using-promises-q-handle-asynchronous-calls/
$http functions are async by default.
And regarding the beforesend function, you could wrap the http call in a function and add the spinner just before making the call and remove it in the success call back. Something like this,
var makeHttpRequest = function(){
$('#someID').addClass('spinner');
$http(req).then(function(){
$('#someID').removeClass('spinner');
//rest processing for success callback
},function(){
$('#someID').removeClass('spinner');
//Error callback
});
}
The way I have implemented complex get and post in my angular application is as below:
Create a CRUDService as below:
yourApp.service('CRUDService', function ($q, $http) {
this.post = function (value, uri) {
var request = $http({
method: "post",
url: uri,
data: value
});
return request;
}
this.get = function (uri) {
var request = $http({
method: "get",
url: uri
});
return request;
}
});
As you can see this service simply returns a get/post object. Somewhere in my controller I use this service as below:
$('#exampleButton').button("loading"); //set the element in loading/spinning state here
var getObj = CRUDService.get("/api/get/something");
getObj.then(function(data){
//do something
$('#exampleButton').button("reset"); //reset element here
}, function(err){
//handle error
$('#exampleButton').button("loading"); //reset element here
});
$('#exampleButton').button("loading"); //set the element in loading/spinning state here
var postObj = CRUDService.post(postData,"/api/get/something");
postObj.then(function(data){
//do something
$('#exampleButton').button("reset"); //reset element here
}, function(err){
//handle error
$('#exampleButton').button("loading"); //reset element here
});
I hope this helps :)
The http call is async - it returns a promise that you can then handle with the try() and catch() methods. You can simply wrap your calls i.e.
function makeRequest() {
$scope.showSpinner = true;
$http
.get('http://www.example.com')
.then(function (response) {
$scope.showSpinner = false;
})
.catch(function (err) {
$scope.showSpinner = false;
});
}
If you would however like you use familiar syntax akin to jQuery then you can push your own custom interceptors. This will allow you intercept the requests and response and do whatever you want. In the below example we call functions if they are defined.
angular
.module('app', [])
.config(appConfig)
.factory('HttpInterceptors', httpInterceptors)
.controller('MyController', myController);
// app config
appConfig.$inject = ['$httpProvider'];
function appConfig($httpProvider) {
// add out interceptors to the http provider
$httpProvider.interceptors.push('HttpInterceptors');
}
// http interceptor definition
function httpInterceptors() {
return {
request: function(request) {
if (angular.isFunction(request.beforeSend)) {
request.beforeSend();
}
return request;
},
response: function(response) {
if (angular.isFunction(response.config.onComplete)) {
response.config.onComplete();
}
return response;
}
}
}
// controlller
myController.$inject = ['$scope', '$http', '$timeout'];
function myController($scope, $http, $timeout) {
$scope.showSpinner = false;
$http({
method: 'GET',
url: 'https://raw.githubusercontent.com/dart-lang/test/master/LICENSE',
beforeSend: function() {
$scope.showSpinner = true;
},
onComplete: function() {
$timeout(function() {
console.log('done');
$scope.showSpinner = false;
}, 1000);
}})
.then(function(response) {
console.log('success');
})
.catch(function(err) {
console.error('fail');
});
}
.spinner {
background-color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular.min.js"></script>
<div ng-app='app' ng-controller='MyController'>
<div ng-class='{spinner: showSpinner}'>
Hello World!
</div>
</div>

AngularJS Display JSON Data

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

Angular JS $http request - caching success response

I've got a simple dataFactory that retrieves some posts:
dataFactory.getPosts = function () {
if (this.httpPostsData == null) {
this.httpPostsData = $http.get("http://localhost/matImms/wp-json/posts?type=journey&filter[posts_per_page]=-1&filter[order]=ASC&filer[orderby]=date")
.success(function (posts) {
})
.error(function (posts) {
console.log('Unable to load post data: ' + JSON.stringify(posts));
});
}
return (this.httpPostsData);
}
The controller calls the factory and I understand that the posts are promises -so there is some stuff done on success and some stuff that is done anyway. This works fine.
.controller('CardsCtrl', function($scope, dataFactory,
$ionicSlideBoxDelegate, $stateParams) {
var parentID = $stateParams.parentID;
var keyIDNumber = $stateParams.keyID;
$scope.card = [];
var httpcall = dataFactory.getPosts()
.success(function (posts) {
$scope.card = dataFactory.getChildPosts(parentID, posts, keyIDNumber);
$ionicSlideBoxDelegate.update();
});
// do other stuff ......
});
However, I'm now trying to cache the post data - but when the controller is called a second time it returns the error .success is not a function. I assume the is because the posts have already been returned - but how do I handle this?
That's because you're not returning the $http.get, you're returning the promise after .success and .error have already been handled.
You can either change the controller to call .then on the return, or change the service to just return the $http.get (remove the .success and .error) and handle them in the controller.
If you change the controller to use .then you'll also need to update the .success function in the service to return posts;.
Have you tried setting the cache option to true in your $http call? Like here https://stackoverflow.com/a/14117744/1283740
Maybe something like this...
angular.module('foo', [])
.factory('dataFactory', ['$http', function($http){
var dataFactory = {
getPosts: getPosts
};
function getPosts(){
var url = "http://localhost/matImms/wp-json/posts?type=journey&filter[posts_per_page]=-1&filter[order]=ASC&filer[orderby]=date"
return $http({ cache: true, url: url, method: 'GET'})
.error(function (posts) {
console.log('Unable to load post data: ' + JSON.stringify(posts));
});
};
return dataFactory;
}])

Categories