AngularJS service with data from REST API - angularjs

I'm starting to read about services in Angular and confused as to how to use them with $http.
I currently use $http to fetch data from my REST API like the code below;
$scope.getRestaurant = function () {
var baseUrl = 'http://api.example.com/web/restaurant/details/' + $scope.id;
$http({
method: 'get',
url: baseUrl,
headers: {'Content-Type': 'application/json'}
}).
success (function(data, status, headers, config){
if(data && !angular.isUndefined(data) ){
$scope.restaurant = data;
} else {
$scope.restaurant = [];
}
}).
error(function(data, status, headers, config) {
//$scope.messageFailure(data.message);
});
}
$scope.id is a value on my controller how can I turn this function into service and then access the data returned in my controller?

This is how you can create a factory or service that has a function which takes an argument, you can then pass $scope.id in your controller to that function.
So to start, create a factory:
app.factory('myFactory', function($http) {
var factory = {};
var _myfunction = function(id)
{
return $http.get('http://api.example.com/web/restaurant/details/'+id);
}
factory.myFunction = _myfunction;
return factory;
});
and then in your controller, you will have:
app.controller('myCtrl', function('myFactory'){
var x = $scope.id;
$scope.getRestaurant = function (x) {
myFactory.myFunction(x).success(function(data, status, headers, config){
//whatever...
}).error(function(){
// whatever....
})
};
});
Of course it's just a general idea, you need to tweak it to meet your exact needs.

You have to inject the service into the controller and talk to it through there.
Quick example:
Your service
app.service '$restaurants', ['$http', '$q', ($http, $q) ->
fetch: (id) ->
deferred = $q.defer()
config =
url: "//api.example.com/web/restaurant/details/#{id}"
method: 'GET'
headers: 'Content-Type': 'application/json'
dataType: 'json'
x = $http config
x.error (data, status) -> deferred reject data, status
x.success (response, status, headers, config) ->
deferred.resolve response
deferred.promise
Controller injects the service
app.controller 'GodClass', ['$restaurants', ($restaurants) ->
$scope.id = 1
$restaurants.fetch($scope.id).then (response) ->
console.log response
Very much simplified but it'll get you the results based on the ID that you pass to the service.

Related

Getting ModelAndView data in angular js controller

I am trying to get the model data in angular js ,but not able to get it . I printed the value on spring mvc side .The data is getting stored and is retrieved successfully with the given key.Can anyone tell me how can I achieve this .
My controller-
#RequestMapping(value = "/home.web", method = RequestMethod.GET, produces = {
"application/json" })
public ModelAndView getUSCity(#RequestParam ("statechoice") String statechoice) {
List<String> msa = new ArrayList<String>();
msa = msaService.getMsaCodes(statechoice);
/*ModelAndView model = new ModelAndView("Home");
model.addObject("cities",msa);
System.out.println(model.getModel().get("cities"));*/
//return msa;
return new ModelAndView("Home", "cities",msa);
}
My angular js -
function MyController($scope, $http) {
$scope.getPersonData = function() {
$http({
method : 'GET',
url : 'home.web'
}).success(function(data, status, headers, config) {
alert(data);
$scope.cities = data;
}).error(function(data, status, headers, config) {
console.log("error");
// called asynchronously if an error occurs
// or server returns response with an error status.
});
};
};
Split your code into controller and service because you should not do api calls from cotroller directly(best case). Services should be used. Controllers are only be used to controlling model to show it in the view.
myService.js
app.service('myService', ['$http', '$q', function($http, $q){
return {
getPersons: function(obj) {
var deferred = $q.defer();
$http({
method : obj.method,
url : obj.url
}).then(function(response) {
deferred.resolve(response);
}, function(error) {
alert(error);
deferred.reject(error);
// called asynchronously if an error occurs
// or server returns response with an error status.
});
return deferred.promise();
};
}
});
myController.js
function MyController('MyController', ['$scope', 'myService', function($scope, myService){
$scope.persons = [];
var obj = {method: 'GET', url: 'home.web'};
myService.getPersons(obj).then(function(response){
$scope.persons = response.data // or $scope.persons = response check yourself
}, function(error){
alert(error);
})
}]);

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
})
}
}]);

AngularJS : service not returning value

I'm trying to write an Angular service and it seems like there is something missing. My problem is its not returning any value to my Angular controller
getPrepTimes() method is not returning the http data
But when I check the network (via Chrome dev tools) it will correctly call the external api and return a json object as a response
#my service
'use strict';
angular.module('recipeapp')
.service('prepTimeService',['$http', function($http){
this.prepTime = getPrepTimes();
function getPrepTimes(){
$http({
url: '/prep_times/index.json',
method: 'GET'
})
.success(function (data, status, header, config){
return data;
});
};
}
]);
#controller
'use strict';
angular.module('recipeapp')
.controller('recipeCtrl', ['$scope', 'prepTimeService', function($scope, prepTimeService){
$scope.prep_time = prepTimeService.prepTime;
}]);
When I checked the method getPrepTimes() with returning a string it works. What could be missing here?
A couple things are wrong with the above. You assign this.prepTime to getPrepTimes(). The () there will invoke getPrepTimes immediately, and not when you actually call it! You also need to utilize callbacks to get your data back and use it:
angular.module('recipeapp').service('prepTimeService',['$http', function($http){
this.prepTime = getPrepTimes;
function getPrepTimes(callback) {
$http({
url: '/prep_times/index.json',
method: 'GET'
}).success(function (data, status, header, config){
callback(data);
});
};
}]);
And now use it like so:
prepTimeService.prepTime(function(data) {
$scope.prep_time = data;
});
Calls to the $http service are async, which means you need to return a promise (and not a value):
this.prepTime = function() {
return $http({
url: '/prep_times/index.json',
method: 'GET'
});
};
And on the controller:
angular.module('recipeapp')
.controller('recipeCtrl', ['$scope', 'prepTimeService', function($scope, prepTimeService){
$scope.prep_time = prepTimeService.prepTime()
.success(function (data, status, header, config){
$scope.someVar = data;
});
}]);
Wrap answer with promise:
var self = this;
var deferred = $q.defer();
self.getPrepTimes = function() {
$http({
url: '/prep_times/index.json',
method: 'GET'
})
.success(function(data, status, headers, config) {
if (data.error === undefined) {
deferred.resolve(data);
} else {
if (data.error !== undefined) {
} else {
deferred.reject(data);
}
}
}).error(function(data, status, headers, config) {
deferred.reject(data);
});
return deferred.promise;
};
In controller call it:
prepTimeService.getPrepTimes().then(function(result) {
$scope.prep_time = result;
},
function(error) {
// show alert
});

Why Dependency injection of a factory inside another factory failing?

I have one factory like this :
app.factory('LoginFactory', [ '$scope', '$http', function($scope, $http) {
var urlBase = "http://localhost:8080/app";
var fact = {};
fact.login = function(userinfo) {
return $http({
method : 'POST',
url : urlBase + '/login',
data : userinfo,
headers : {
'Content-Type' : 'application/json',
'Accept' : 'application/json'
}
});
};
fact.validate = function(sessionId) {
return $http({
method : 'GET',
url : urlBase + '/validate?sessionId=' + sessionId,
});
};
return fact;
} ]);
And Another factory like this :
app.factory('LoginService', [
'Credentials',
function(Credentials, $location, LoginFactory) {
var fact = {};
fact.isLoggedin = function() {
var result = false;
LoginFactory.validate(Credentials.sessionId).success(
function(data, status, headers, config) {
result = true;
}).error(function(data, status, headers, config) {
result = false;
});
return result;
};
fact.authenticate = function(userinfo) {
LoginFactory.login(userinfo).success(
function(data, status, headers, config) {
Credentials = data;
$location.path('/home');
}).error(function(data, status, headers, config) {
$location.path('/login');
});
};
return fact;
} ]);
In the Browser Console I am getting the following error :
Error: LoginFactory is undefined
Can anyone please help me out with this error.
Thanks a lot in advance.
You're declaring your service using the array notation, taking the names of the dependencies to inject followed by the function defining the factory. But you said you only wanted to inject Credentials:
app.factory('LoginService', [
'Credentials',
function(Credentials, $location, LoginFactory) {
So angular only injects Credentials. The above should be replaced by
app.factory('LoginService', [
'Credentials', '$location', 'LoginFactory'
function(Credentials, $location, LoginFactory) {
To avoid those bugs, and the repetition of service names in the array and in the function, I strongly suggest using ngAnnotate in your build.

AngularJS - Controller gets the data returned from Service (MVC Web API call) as undefined

I am new to AngularJS & working on a sample. In my sample app I have an MVC Web api (which returns some data from db) & it will be called from the Angular Services and returns the data to the Controller. The issue is I am getting the data in my Services success method properly but in my controller it always shows undefined & nothing is displayed in the view. Please see the code below:
My Controller code:
app.controller('CustomerController', function ($scope, customerService) {
//Perform the initialization
init();
function init() {
$scope.customers= customerService.getCustomers();
}
});
My Services code:
app.service('customerService', function ($http){
this.getCustomers = function () {
$http({
method: 'GET',
url: 'api/customer'
}).
success(function (data, status, headers, config) {
return data;
}).
error(function (data, status) {
console.log("Request Failed");
});
}
});
Please help me to fix this issue.
That's because your service defines the function getCustomers but the method itself doesn't actually return anything, it just makes an http call.
You need to provide a callback function in the form of something like
$http.get('/api/customer').success(successCallback);
and then have the callback return or set the data to your controller. To do it that way the callback would probably have to come from the controller itself, though.
or better yet, you could use a promise to handle the return when it comes back.
The promise could look something like
app.service('customerService', function ($http, $q){
this.getCustomers = function () {
var deferred = $q.defer();
$http({
method: 'GET',
url: 'api/customer'
}).
success(function (data, status, headers, config) {
deferred.resolve(data)
}).
error(function (data, status) {
deferred.reject(data);
});
return deferred;
}
});
Your problem is in your service implementation. You cannot simply return data since that is in the asynchronous success callback.
Instead you might return a promise and then handle that in your controller:
app.service('customerService', function ($http, $q){
this.getCustomers = function () {
var deferred = $q.defer();
$http({
method: 'GET',
url: 'api/customer'
})
.success(function (data, status, headers, config) {
// any required additional processing here
q.resolve(data);
})
.error(function (data, status) {
q.reject(data);
});
return deferred.promise;
}
});
Of course if you don't require the additional processing, you can also just return the result of the $http call (which is also a promise).
Then in your controller:
app.controller('CustomerController', function ($scope, customerService) {
//Perform the initialization
init();
function init() {
customerService.getCustomers()
.then(function(data) {
$scope.customers= data;
}, function(error) {
// error handling here
});
}
});
VERY late answer, but, Angular's $http methods return promises, so there's no need for wrapping everything into promise form with $q. So, you can just:
app.service('CustomerService', function ($http) {
this.getCustomers = function () {
return $http.get('/api/customer');
};
});
and then call the .success() or .error() shortcut methods in your client controller.
If you want to take it a step further and have a fully-fledged RESTful CustomerService without having to write this boilerplate, I'd recommend the restangular library, which makes all sorts of methods available to you - assuming of course your backend responds to HTTP verbs in the "standard fashion".
Then you could just do this:
app.service('CustomerService', function (Restangular) {
return Restangular.service('api/customer');
});
and call the methods Restangular makes available to you.
I use this for communication between Angular Web Data Service and Web Api Controller.
.factory('lookUpLedgerListByGLCode', function ($resource) {
return $resource(webApiBaseUrl + 'getILedgerListByGLCode', {}, {
query: { method: 'GET', isArray: true }
});
})
OR
.factory('bankList', function ($resource) {
return $resource(webApiBaseUrl + 'getBanklist_p', {}, {
post: {
method: 'POST', isArray: false,
headers: { 'Content-Type': 'application/json' }
}
});
})

Resources