I've been using custom actions in a few repositories. And up until now I only had to specify the url and the method.
For example:
updatePassword: {
url: ENV.NITRO_PROJECT_REST_URL + '/admins/:adminId/password',
method: 'PUT'
}
But then, I had to code a custom action that had, not one, but two path parameters:
technicianModule.controller('technician.teamCtrl',
['$scope', '$state', '$stateParams', 'CommonService', 'TechnicianService', 'TeamService', 'TeamTechnicianService',
function($scope, $state, $stateParams, CommonService, TechnicianService, TeamService, TeamTechnicianService) {
$scope.add = function(teamId) {
TeamTechnicianService.add(teamId, $stateParams.technicianId, function() {
TeamService.get(teamId, function(data) {
$scope.teams.push(data);
$scope.unassignedTeams.splice(CommonService.getResourceIndex($scope.unassignedTeams, data), 1);
});
});
};
}
]);
teamModule.factory('TeamTechnicianService',
['RESTService',
function(RESTService) {
var factory = {};
factory.add = function(teamId, technicianId, callback) {
return RESTService.TeamTechnician.add({teamId: teamId, technicianId: technicianId}).$promise.then(callback);
}
return factory;
}
]);
So I first coded it like:
TeamTechnician: $resource(ENV.NITRO_PROJECT_REST_URL + '/teamtechnicians/:teamtechnicianId', {}, {
add: {
url: ENV.NITRO_PROJECT_REST_URL + '/teamtechnicians/:teamId/:technicianId',
method: 'POST'
}
But it would not work. The parameters were not passed in.
After a few tries I found out it worked when adding some parameter definition, right before the custom action definition.
It had to be like:
TeamTechnician: $resource(ENV.NITRO_PROJECT_REST_URL + '/teamtechnicians/:teamtechnicianId', {
teamId: '@teamId',
technicianId: '@technicianId'
}, {
add: {
url: ENV.NITRO_PROJECT_REST_URL + '/teamtechnicians/:teamId/:technicianId',
method: 'POST'
}
Note the presence of:
teamId: '@teamId',
technicianId: '@technicianId'
My understanding was then that in a $resource definition, a custom action that has more than one path parameter, requires them to be defined with @ signs.
And not when it has only one.
Why is that ?
And why can't the path parameters be declared in the custom action instead of above in the resource ?
The parameters can be declared per custom action.
The default parameters are what their name implies: default parameters (as in: "used in case other parameters are not provided").
The use of '@'
(either in default parameters or in action parameters) is not mandatory.
It is provided as a convenience and has a special meaning. paramKey: '@someProp'
means:
"For methods that have a request body (e.g. POST, PUT etc), if I do not explicitly provide a value for the parameter paramKey
, please look into my data object for a property named someProp
and use its value as the value for the paramKey
parameter."
Note that when you use a class method, you have to explicitly provide the data object:
SomeResourceClass.save({.../* data object */...});
When you use an instance method, the instance itself acts as the data object:
var instance = SomeResourceClass.get(...);
instance.$save(); /* `instance` will act as the data object. */
See, also, this short demo.
UPDATE:
It seems like you want to call the following custom action:
add: {
url: ENV.NITRO_PROJECT_REST_URL + '/teamtechnicians/:teamId/:technicianId',
method: 'POST'
}
Trying to call it like this <ResourceClass>.add({teamId: teamId, technicianId: technicianId})
does not work as expected, as it interpret the (intended to be) params object as a data object.
From the ngResource
documentation, the method signatures for "non-GET" methods (like yours) are:
From the above exerpt, it is clear that if you only pass one object in "class" action call, then it is interpreted as the data
object (the request's payload). Additionally, if you have @
-prefixed default parameters, then the URL parameters are going to get resolved against that data
object (which is why it worked with default parameters).
In order for Angular to interpret the params
object as a params
(and not data
object) and since the data
param is mandatory, you need to call it like this:
<ResourceClass>.add({teamId: teamId, technicianId: technicianId}, {})
(Alternatively, you could be using a TeamTechnician
instance, but that's another story.)
When you define a $resource the definition looks like this
$resource(url, [paramDefaults], [actions]);
The second parameter paramDefaults
is just there to provide default values. The @
syntax is used to derive the parameter value from the payload of a PUT or POST request.
You can always provide parameter values while actually invoking the resource action. If you don't then the default parameter values are taken and if that too are not there then the fragment is removed.
What can be parameterized needs to be define on $resource using the :
syntax and same goes for what the default value is.
For the action method they just take the same $http config
object.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With