I'm trying to using the $resource library of angular, to POST data to a nested resource.
My following nested resource of event looks like so
events/:eventId/match - POST
events/:eventId/match - GET
events/:eventId/match/:matchId - GET
I set up a service with angular
app.factory('EventService', ['$resource', function ($resource) {
var Event = $resource('/events/:eventId', {eventId: '#id'},
{
createMatches: {
url: '/events/:eventId/match',
method: 'POST'
}
);
return {
createMatches: function(data,event_id) {
var data.eventId = event_id;
return Event.createMatches(data).$promise;
}
}
});
Controller where it has been called:
app.controller('EventController', ['$scope','EventService', function($scope,EventService) {
$scope.create = function(event_id,title,description) {
EventService.createMatches({
title:title,
description: description
},event_id).then(function(result) {
console.log('event_created', result);
})
}
}]);
Problem
When I send the request to the server I expect the url that looks like so: /events/10/match
But instead the resource doesn't add the eventId as a parameter of the url but add it as a parameter of the request, for this reason my call fail because the url looks like so: /events/match.
I can't understand why it doesn't bind the :eventId to the url. Any suggest will be appreciated.
I believe that you are missing your second parameter decalaration, as per this link for the actions you are defining:
app.factory('EventService', ['$resource', function ($resource) {
var Event = $resource('/events/:eventId', {eventId: '#id'},
{
createMatches: {
url: '/events/:eventId/match',
method: 'POST',
params: {eventId: '#id'}
}
);
return {
createMatches: function(data,event_id) {
var data.eventId = event_id;
return Event.createMatches(data).$promise;
}
}
});
Related
Is there a more elegant/correct way to compose an url with $http in AngularJS?
I find my self doing a lot of this:
$http.post('/api/' + model_id + '/' + id).success(function(data){
//do something ..
});
and wandering if there was something like this (a little more readable)
$http.post('/api/:model_id/:id', {param1, param2}).success(function(data){
//do something ..
});
Thanks
I use the following pattern:
o in a service called resources I create resources as follows (assuming my webservces are unter the URL path /webapi):
angular.module('myApp')
.factory('resources', function ($resource) {
var baseUrl = location.pathname + 'webapi';
return {
baseUrl: baseUrl,
myServiceResource: $resource(baseUrl + '/my/service/:pathParam'),
myOtherServiceResource: $resource(baseUrl + '/my/other/service')
// etc.
};
});
o in a controller or another service you can then simply reference the resources service and use the globally defined resources (which are created only once):
angular.module('myApp')
.factory('aService', function (resources) {
// pathParam matches the parameter :pathParam in the URL
// param1 and param2 are passed as query parameters
var parameters = { pathParam: "pathValue", param1: "aValue", param2: "anotherValue" };
var response = resources.myServiceResource.get(parameters, function() {
// do something on success
doSomething(response.result);
}, function(httpResponse) {
// do something on error
});
});
Not with $http directly, but it seems you are looking for $resource (https://docs.angularjs.org/api/ngResource/service/$resource).
Example from docs:
// Define CreditCard class
var CreditCard = $resource('/user/:userId/card/:cardId',
{userId:123, cardId:'#id'}, {
charge: {method:'POST', params:{charge:true}}
});
// We can retrieve a collection from the server
var cards = CreditCard.query(function() {
// GET: /user/123/card
// server returns: [ {id:456, number:'1234', name:'Smith'} ];
var card = cards[0];
// each item is an instance of CreditCard
expect(card instanceof CreditCard).toEqual(true);
card.name = "J. Smith";
// non GET methods are mapped onto the instances
card.$save();
// POST: /user/123/card/456 {id:456, number:'1234', name:'J. Smith'}
// server returns: {id:456, number:'1234', name: 'J. Smith'};
// our custom method is mapped as well.
card.$charge({amount:9.99});
// POST: /user/123/card/456?amount=9.99&charge=true {id:456, number:'1234', name:'J. Smith'}
});
// we can create an instance as well
var newCard = new CreditCard({number:'0123'});
newCard.name = "Mike Smith";
newCard.$save();
// POST: /user/123/card {number:'0123', name:'Mike Smith'}
// server returns: {id:789, number:'0123', name: 'Mike Smith'};
expect(newCard.id).toEqual(789);
I use the following pattern because it allows me to implement my own error handling logic when API calls is failed, also I found that it is readable and easy to understand.
angular.module('myApp')
.service('myService', function($http, $q) {
var baseUrl = location.pathname + 'webapi';
return({
setService: setService,
getService: getService
});
function setService(param1, param2) {
var request = $http({
method: 'post',
url: baseUrl,
params: {
param1: param1,
param2: param2
}
});
return ( request.then ( handleSuccess, handleError) );
}
function getService(param1, param2) {
var request = $http({
method: 'get',
url: baseUrl,
params: {
param1: param1,
param2: param2
}
});
return ( request.then ( handleSuccess, handleError) );
}
function handleError( response ) {
// Implement our own failure message if there is none
if ( !angular.isObject(response.data) || !response.data.message) {
return($q.reject("Failed to get data.") );
}
return($q.reject(response.data.message));
}
function handleSuccess( response ) {
return response;
}
});
I have created a Angular resource that sends POST data to a web service. Here is my factory:
appServices.factory('Foo', function($resource) {
var data = $resource(
'http://localhost:3000/api/v1/foo.json',
{},
{
'save': {
method: 'POST',
cache: false
}
});
return data;
});
Here's my Controller:
appControllers.controller('FooCtrl', function($scope, Foo, $location) {
$scope.memberData = {};
$scope.create = function() {
var member = new Foo();
member.$save( {}, { bar: bar });
$location.url("/");
};
});
When I submit the form in my client, it returns a 500 status. Looking into Firebug, I can see that my POST data payload always remains empty for some reason.
What am I doing wrong?
PS. I've added this to my config: $httpProvider.defaults.headers.post['Content-Type'] = 'application/json; charset=utf-8';
If you want to issue a POST request to the member resource, you can use save() (without the $) and pass in your body as the first argument:
Foo.save({bar: 'bar'}, function () {
// Callback
});
However, when creating a new resource instance, it is augmented with a $save() method (note the $). When you invoke this method, the instance itself is sent as the body. So you should change your code to:
var member = new Foo();
member['bar'] = 'bar';
member.$save(function () {
// Callback
});
Check this article for more information.
I have a generic restful resource with angular's $resource. On any save method, I also want to set a message and boolean on whatever scope I'm in, and set a timeout for that message. So anywhere in my code where I call .save/.$save, I then attach a .finally onto it (below).
Rather than putting the same .finally onto every save I call, I'm wondering if I can just write a finally onto the actual resource itself, and have this be a generic finally for my save function.
var resource = $resource(
pageListPath,
{},
{
query: {method:'GET', isArray:true},
get: {method:'GET', url: pageDetailPath, params:{id:'#id'}, cache:true},
save: {method:'PUT', url: pageSavePath, params:{id:'#id'}},
delete: {method:'DELETE', url: pageDetailPath, params:{id:'#id'}}
}
);
return resource;
.finally(function() {
$scope.loading = false;
$timeout(function() {
$scope.message = false;
}, 2500);
});
Ideally something like
save: {
method:'PUT',
url:pageSavePath,
params:{id:'#id'},
finally:function() { doStuff() }}
is what I'm looking for. Is this possible?
I ended up writing another service to encapsulate this one, providing generic functionality for certain responses.
The API service:
pageServices.factory('PageAPI',
['$resource',
function($resource,
var resource = $resource(
pageListPath,
{},
{
query: {
method:'GET',
isArray:true
},
get: {
method:'GET',
url: pageDetailPath,
params:{ id:'#id' }
},
...,
...,
}
);
return resource;
}]
);
pageServices.factory('Page', ['PageAPI',
function(PageAPI) {
var service = {
'getPages': function() {
return PageAPI.query(function(response) {
// Do stuff with success
}, function(err) {
// Handle error
}).$promise.finally(function() {
// Generic finally handler
}
},
...,
...,
}
return service
}
])
I am trying to build my first Angular $resource to give my application access to CRUD operations, but for some reason the actions being configured for the resource are not defined when I try to execute a query.
Here is my controller logic:
app.controller('MainCtrl', function ($scope, $http, $resource) {
var Alert = $resource('/WebApi/Alert/:type/:id',
{
systemUpdate: { method: 'GET' },
autoArchive: { method: 'POST', url: '/WebApi/Alert/Template/:type' }
});
$scope.systemUpdate = function (alert) {
var data = Alert.systemUpdate({ type: alert.Status, id: alert.AlertId }); // THIS LINE FAILS
console.log(data);
}
I get an error saying that Alert.systemUpdate is not defined. Am I doing something wrong here when configuring my $resource?
Change the definition of your Alert to
var Alert = $resource('/WebApi/Alert/:type/:id',
{},
{
systemUpdate: { method: 'GET' },
autoArchive: { method: 'POST', url: '/WebApi/Alert/Template/:type' }
});
As mentionned in the documentation of $resource, the order of the parameters is the following:
1) Url
2) The default value of the parameters of the url, since you don't have any default value, you must provide an empty object
3) The actions (systemUpdate & autoArchive here)
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'
});