Rest Webservice call in AngularJS ( promise ) - angularjs

AngularJS : 1.4.X
Scenario 1: Works fine
Scenario 2: Throws 404 error on line xhr.send(isUndefined(post) ? null : post); in angular.js
I'm trying to add inbuilt angular cache to our existing app, As i mentioned in scenario 1 we consume rest call in factory 'restFactory' and inject the factory to controller 'bookController', the promise is resolved and data loads fine.
Factory: restFactory
(function () {
"use strict";
angular.module('myApp').factory("restFactory",['$http','confi', function($http,config){
function getBooks (){
return $http.get(config.serverName+"bookshelf/rest/books/data/geRestBooks");
}
return {
getBooks : getBooks
};
}]);
})();
Controller: bookController
$scope.getComicbooks = function() {
restFactory.getBooks().then(function(response) {
$scope.names = response.data;
}, function(error) {
$scope.error = error;
$scope.names = [];
});
};
Now in scenario 2, I changed the service call in factory to object with more details. But i get exception from controller while resolving the promise ( i have only added the changed code )
function getBooks (){
return $http.get({
cache: true,
method: 'GET',
url : config.serverName+"bookshelf/rest/books/data/geRestBooks"
});
}
ERROR: angular.js:10765 GET http://127.0.0.1:53814/views/[object%20Object] 404 (Not Found)
Network Tab:
In scenario#1 this would have been a method call getBooks

If you are going to specify the method, then you should just use the $http constructor method, not the get method.
Instead of
function getBooks (){
return $http.get({
cache: true,
method: 'GET',
url : config.serverName+"bookshelf/rest/books/data/geRestBooks"
});
}
Try
function getBooks (){
return $http({
cache: true,
method: 'GET',
url : config.serverName+"bookshelf/rest/books/data/geRestBooks"
});
}

Related

Angular - Having troubles receiving $http response from a factory

I have an angular factory doing some $http communication to the server and returning a string. However I get the Cannot read property 'then' of undefined error. I read here and here with similar problems however I was not able to resolve my problem.
This is the service code:
factory("availabilityService", ['$http', function ($http) {
return {
checkAvailability1: function (element, string) {
// ..... some object creation code ......
$http({
method: 'POST',
url: 'server/server.php',
data: AvailableObj,
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
})
.then(function successCallback(response) {
return response;
}, function errorCallback(response) {
});
}
}
}]);
Inside a controller:
$scope.checkAvailability = function (element, string) {
availabilityService.checkAvailability1(element, string).then(function (response) { //on this line the error occurs
console.log(response);
});
You need to return the promise returned by $http i.e add a 'return' in front of $http to get your code working like below :
return $http(...)
.then(function successCallback(response) {
return response;
}, function errorCallback(response) {
});
This is because, the function you have called from the controller should have a .then method on it i.e it should be a promise. checkAvailability1 in angular returns a promise which needs to be returned back by your function $http in the factory. You are just returning the response from the success callback which is not expected by your method in the controller.

Data bind works only on second click event

I have a click event to call the AngularJS function which retrieves the data from SQL and return to the ajax call.
My problem is the data which is retrieved binds with ng-repeat only on the second click event.Here is my code,
`
(function (app) {
app.controller("OnvioController", function ($scope,$http, OnvioService) {
$scope.retData = [];
$scope.getResult = function () {
var serviceURL =window.location.origin+ '/Datafetching/dataFetch';
$.ajax({
type: "POST",
url: serviceURL,
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(data, status) {
$scope.retData = data;
},
error: function (status) {
}
});
}
});
}(angular.module("OnvioModule")));
`
Do not use $.ajax in angularJS.
You can do this by $http.get
I haven't tried it my self right now. but it should work in your case.
(function (app) {
app.controller("OnvioController", function ($scope,$http, OnvioService) {
$scope.retData = [];
$scope.getResult = function () {
var serviceURL =window.location.origin+ '/Datafetching/dataFetch';
$http.get(serviceURL).success( function(response) {
$scope.retData = response;
});
}
});
}(angular.module("OnvioModule")));
refer this document for more details
Use $http.post instead of $.ajax.
If you still want to use $.ajax add a $scope.$apply() in your success function.
This will trigger angular loop to search for changes outside of his context. This is because $.ajax is executing outside of angular stuff.
Add a $scope.$apply() in your success function.

Angular Service - Pass $http data to scope

I´m trying to create an angular function inside on Service to return acess data via $http and then return to a desired scope.
So my service it something like this;
app.service('agrService', function ($http) {
this.testinho = function(){
return "teste";
}
this.bannerSlides = function(){
var dataUrl = "data/banner-rotator.json";
// Simple GET request example :
$http({
method: 'GET',
dataType: "json",
url: dataUrl
})
.success( function(data, status, headers, config) {
// this callback will be called asynchronously
// when the response is available
//console.log(data);
return data;
}).error( function(data, status, headers, config) {
// called asynchronously if an error occurs
// or server returns response with an error status.
alert("Niente, Nada, Caput");
});
}
})
Then i want to associate the returned data to a scope inside of my main App controller... like this:
app.controller('AppCtrl', function($scope, $http, agrService) {
$scope.slides = agrService.bannerSlides();
})
Then in my template i want to loop the data like this:
<div ng-repeat="slide in slides">
<div class="box" style="background: url('{{ slide.url }}') no-repeat center;"></div>
</div>
The problem is that the data it´s only available on success and i don´t know how to pass it to my scope slides!!!!!
What i´m doing wrong?
Many thanks in advance
bannerSlides() doesn't return the values you need right away. It returns a promise that you can use to obtain the value at a later time.
In your service you can use the .then() method of the promise that $http() produces to do initial handling of the result:
return $http({
method: 'GET',
dataType: "json",
url: dataUrl
}).then(function (data) {
// inspect/modify the received data and pass it onward
return data.data;
}, function (error) {
// inspect/modify the data and throw a new error or return data
throw error;
});
and then you can do this in your controller:
app.controller('AppCtrl', function($scope, $http, agrService) {
agrService.bannerSlides().then(function (data) {
$scope.slides = data;
});
})
Use this in your service
....
this.bannerSlides = function(){
var dataUrl = "data/banner-rotator.json";
return $http({
method: 'GET',
dataType: "json",
url: dataUrl
});
};
...
And this in your controller
agrService.bannerSlides().then(function(data) {
$scope.slides = data;
}, function() {
//error
});
you don't need $q promise inside the service because the $http is returning a promise by default
The $http service is a function which takes a single argument — a configuration object — that is
used to generate an HTTP request and returns a promise with two $http specific methods: success and error
reference
here is a Fiddle Demo
You need to return a promise and update your scope in the callback:
app.service('agrService', function ($q, $http) {
this.bannerSlides = function(){
var ret = $q.defer();
var dataUrl = "data/banner-rotator.json";
// Simple GET request example :
$http({
method: 'GET',
dataType: "json",
url: dataUrl
})
.success( function(data, status, headers, config) {
// this callback will be called asynchronously
// when the response is available
ret.resolve(data);
}).error( function(data, status, headers, config) {
// called asynchronously if an error occurs
// or server returns response with an error status.
ret.reject("Niente, Nada, Caput");
});
return ret.promise;
}
})
app.controller('AppCtrl', function($scope, $http, agrService) {
$scope.slides = null;
agrService.bannerSlides().then(function(data){
$scope.slides = data;
}, function(error){
// do something else
});
})
You can't return a regular variable from an async call because by the time this success block is excuted the function already finished it's iteration.
You need to return a promise object (as a guide line, and preffered do it from a service).
Following angular's doc for $q and $http you can build yourself a template for async calls handling.
The template should be something like that:
angular.module('mymodule').factory('MyAsyncService', function($q, http) {
var service = {
getData: function() {
var params ={};
var deferObject = $q.defer();
params.nameId = 1;
$http.get('/data', params).success(function(data) {
deferObject.resolve(data)
}).error(function(error) {
deferObject.reject(error)
});
return $q.promise;
}
}
});
angular.module('mymodule').controller('MyGettingNameCtrl', ['$scope', 'MyAsyncService', function ($scope, MyAsyncService) {
$scope.getData= function() {
MyAsyncService.getData().then(function(data) {
//do something with data
}, function(error) {
//Error
})
}
}]);

how to make Generic method for rest call in angularjs

how to make Generic method for rest call in angularjs ?
i have tried for single request, it's working fine
UIAppRoute.controller('test', ['$scope', 'checkStatus', function($scope, checkStatus) {
$scope.data = {};
checkStatus.query(function(response) {
$scope.data.resp = response;
});
}])
UIAppResource.factory('checkStatus', function($resource){
return $resource(baseURL + 'status', {}, {'query': {method: 'GET', isArray: false}})
})
I want to make this as generic for all the request
Please share any sample,.. thanks in advance
I'm using something like this :
.factory('factoryResource', ['$resource', 'CONF',
function($resource, CONF) {
return {
get: function(endPoint, method) {
var resource = $resource(CONF.baseUrl + endPoint, {}, {
get: {
method: method || 'GET'
}
});
return resource.get().$promise;
}
};
}
])
called by :
factoryResource.get(CONF.testEndPoint, "POST"); // make a POST and return a promise and a data object
factoryResource.get(CONF.testEndPoint, "GET"); // make a GETand return a promise and a data object
factoryResource.get(CONF.testEndPoint); // make a GETand return a promise and a data object
with a config file having :
angular.module('app.constant', [])
.constant('CONF', {
baseUrl: 'http://localhost:8787',
testEndPoint: '/api/test'
});

AngularJS - scope variable does not get updated from method

I'm totally new to AngularJs and I have this problem I do not understand. I have two methods. The first one takes some data from a webservice and puts in in a variable defined in the scope. But when I want to use that variable in the second method it is undefined. Can someone help me understand why this is happening and provide a solution?
var myApp= angular.module( "myApp", [] );
myApp.controller("myAppController",
function( $scope ) {
$scope.getAll = function(){
$.ajax({
type: "GET",
dataType: "jsonp",
contentType: "application/json; charset=utf-8",
url: ..something...,
success: function (parameters) {
$scope.profiles = angular.copy(parameters); <-- correct data is returned
$scope.$apply();
},
error: function () {
alert("Error calling the web service.");
}
});
}
$scope.getCategories = function(){
var all = $scope.profiles; <-- At this point profiles is empty
...
}
$scope.getAll();
$scope.getCategories();
}
Use the $http service and promises:
$scope.profiles = $http.jsonp(url).then(function(r){ return r.data; });
$scope.categories = $scope.profiles.then(function(profiles) {
var params = { }; // build url params
return $http.jsonp(url, { params: params }).then(function(r){ return r.data; });
});
When you call getCategories(), getAll() hasn't finished yet, which is why profiles is empty. There are several ways to solve this. The best way would be to use promises the built-in $http service.
If you prefer to use jQuery, you can add a watcher on the profiles variable and only when it's populated run the getCategories().
Something like this should work:
$scope.getAll = function(){
$.ajax({
type: "GET",
dataType: "jsonp",
contentType: "application/json; charset=utf-8",
url: ..something...,
success: function (parameters) {
$scope.profiles = angular.copy(parameters); <-- correct data is returned
$scope.$apply();
},
error: function () {
alert("Error calling the web service.");
}
});
}
$scope.getCategories = function(){
var all = $scope.profiles;
}
// Wait for the profiles to be loaded
$scope.watch('profiles', function() {
$scope.getCategories();
}
$scope.getAll();
There is no guarantee that getAll has completed before getCategories is invoked, since it is an asynchronous request. So if you want to sequentially invoke getAll and getCategories, you should invoke getCategories inside the success callback of getAll. You could also look into promises for a neater way of chaining asynchronous callbacks (I assume you're using jQuery since you're calling $.ajax).
...
<snipped some code>
success: function(parameters) {
// snipped more code
$scope.getCategories();
}
(and if you're using jQuery promises)
$.ajax(ajaxCallOneOpts).then($.ajax(ajaxCallTwoOpts));
Neither are very "Angularish" though, so you might want to look into some of the provided services for working with http/rest resources instead of using jQuery.
Why are you using a jQuery ajax request in angular? If you write jQuery style code and wrap it angular, you're going to have a bad time...
Here is an angularised version:
myApp.controller("myAppController",
function( $scope, $q, $http ) {
$scope.getAll = function(){
var deferred = $q.defer();
$scope.profiles = deferred.promise;
$http.jsonp('your url').then(function(data) {
deferred.resolve(data);
});
});
$scope.getCategories = function(){
$q.when($scope.profiles).then(function(profiles) {
... <-- At this point profiles is populated
});
}
$scope.getAll();
$scope.getCategories();
}

Resources