I have a $resource
whose API will always return some data that needs to be cleaned up before going into the presentation layer. Specifically, it's .NET returning Date objects in the lovely '/Date(...)/'
format.
I don't want to have to write a callback every time I call .query()
or .get()
. Is there some way to extend the resource with a callback that gets called upon REST methods that update the instance's properties, or by adding some sort of $watch
that gets fired when the date property changes? Basically something that will happen for every instance of this $resource
.
angular.module('myAppServices', ['ngResource'])
.factory('Participant', ['$resource', function ($resource) {
var res = $resource('api/url/participants/:id', { id: '@id' });
// This obviously doesn't work, but something kinda like this?
res.prototype.$watch(this.FieldName, function(newVal, oldVal) {
if (needsCleaning(newVal.fieldName) {
this.FieldName = cleanupField(newVal);
}
};
});
I have a $resource
whose API will always return some data that needs to be cleaned up before going into the presentation layer. Specifically, it's .NET returning Date objects in the lovely '/Date(...)/'
format.
I don't want to have to write a callback every time I call .query()
or .get()
. Is there some way to extend the resource with a callback that gets called upon REST methods that update the instance's properties, or by adding some sort of $watch
that gets fired when the date property changes? Basically something that will happen for every instance of this $resource
.
angular.module('myAppServices', ['ngResource'])
.factory('Participant', ['$resource', function ($resource) {
var res = $resource('api/url/participants/:id', { id: '@id' });
// This obviously doesn't work, but something kinda like this?
res.prototype.$watch(this.FieldName, function(newVal, oldVal) {
if (needsCleaning(newVal.fieldName) {
this.FieldName = cleanupField(newVal);
}
};
});
Share
Improve this question
edited Aug 27, 2013 at 15:09
Scotty.NET
12.6k4 gold badges45 silver badges52 bronze badges
asked Apr 5, 2013 at 19:08
c0brac0bra
3,01224 silver badges34 bronze badges
1
|
3 Answers
Reset to default 12Ah-ha, I found a way around it and will leave it here. In version 1.1.2 they added support for passing all the $http.config
options to a $resource
. Naturally, the CDN I'm using doesn't have a recent enough version of angular-resource.js, but switching CDNs solved that.
I just used the transformResponse
option to modify the data as it comes back.
angular.module('myAppServices', ['ngResource'])
.factory('Participant', ['$resource', '$http', function ($resource, $http) {
var res = $resource('api/url/participants/:id', { id: '@id' }, {
save: {
method: 'POST',
transformResponse: $http.defaults.transformResponse.concat([
function (data, headersGetter) {
data.FieldName = yourDateParsingFunction(data.FieldName);
return data;
}
])
}
});
I'm just adding my transformer on to $httpProvider
's transformResponse, which will do all the deserialization, etc.
An easy way to do this is to overwrite the existing $resource
methods you want to do post-processing on with your own. See the code and comments below for an example.
angular.module('myAppServices', ['ngResource'])
.factory('Participant', ['$resource', function ($resource) {
var res = $resource('api/url/participants/:id', { id: '@id' }, {
// create aliases for query and get to be used later
_query: { method: 'GET', isArray: true },
_get: { method: 'GET' }
});
// redefine the query method
res.query = function() {
// call the original query method via the _query alias, chaining $then to facilitate
// processing the data
res._query.apply(null, arguments).$then(function(res) {
var data = res.data;
// do any processing you need to do with data here
return data;
});
};
// redefine the method
res.get = function() {
// call the original get method via the _get alias, chaining $then to facilitate
// processing the data
res._get.apply(null, arguments).$then(function(res) {
var data = res.data;
// do any processing you need to do with data here
return data;
});
};
return res;
});
You'd use it the same way you're currently using Participant
in your code, via Participant.query()
or Participant.get()
. The data you return in the chained $then handler will be used to resolve the promise returned by $resource
.
The way I did it was by adding a service to the module:
angular.module('keeniolab', ['ngResource']).
factory('KeenIO',function ($resource) {
// factory implementation
}).service('KeenModel', function (KeenIO) {
var KeenSession = function () {
this.data = {};
};
KeenSession.prototype.fetch = function (query) {
var self = this;
KeenIO.get(query, function (result) {
self.data = result;
});
};
return new KeenSession();
});
Now you can simply monitor the collection:
$scope.$watchCollection(function () {
return KeenModel.data;
},
function (value) {
// code here
});
Keen.IO Resource Factory with Service Model
var participant = $resource('api/url/participants/:id', { id: '@id' }); var commonCallback = function(){ // inside this callback, participant is the populated model, // you can use participant object to do your formatting logic. // Then, if you would like to save the participant object do //participant.$save(); Please not the $ prefixed method names that becomes available to your resources instances. } res.query(commonCallback) or res.get({..}, commonCallback)
– Rajkamal Subramanian Commented Apr 5, 2013 at 20:11