How to contact a non-standard API using Angular ngResource - angularjs

The API I am using requires a non-standard where clause if I try to search for a particular non-id field. The endpoint I need is:
http://127.0.0.1:4001/api/testusers/findOne?userName=Anton
So this will find me the first record in the testusers table whose column (userName) = 'Anton'.
My standard service is:
angular.
module('shared.testUser').
factory('TestUser', ['$resource',
function($resource) {
return $resource('http://127.0.0.1:4001/api/testusers/:id', {id:'#id'},//parameters
{
update: {
method: 'PUT' // To send the HTTP Put request when calling this custom update method.
}
});
}
]);
and my calling function is:
self.checkUsersEntryDirection = function(){ //NOT WORKING
self.testuser = TestUser.get({ username: 'anton' }, function() {
console.log(angular.toJson(self.testuser));
}); // get() returns a single entry
}
Clearly this doesn't work and I can't use the standard get approach. Can anyone think how this can be achieved?

You could create a secondary factory TestUserByName, and make the following changes:
angular.
module('shared.testUser').
factory('TestUserByName', ['$resource',
function($resource) {
return $resource('http://127.0.0.1:4001/api/testusers/findOne?userName:username', null,
{
update: {
method: 'PUT' // To send the HTTP Put request when calling this custom update method.
}
});
}
]);

Call the get action method with two parameters:
var params = {id: "findOne", username: "anton"};
self.checkUsersEntryDirection = function(){
self.testuser = TestUser.get(params, function() {
console.log(angular.toJson(self.testuser));
}); // get() returns a single entry
}
The id parameter will override the default and username parameter will be added as a query string.
From the DOCS:
Each key value in the parameter object is first bound to url template if present and then any excess keys are appended to the url search query after the ?.
Given a template /path/:verb and parameter {verb:'greet', salutation:'Hello'} results in URL /path/greet?salutation=Hello.
--AngularJS ngResource $resource Service API Reference

Related

How to get a where clause using ngResource in angularJS

I have a simple service given here and I want to get a record(s) using a where clause, i.e. the endpoint would http://127.0.0.1:4001/api/testusers?userName=anton
The service is:
angular.
module('shared.testUser').
factory('TestUser', ['$resource',
function($resource) {
return $resource('http://127.0.0.1:4001/api/testusers/:id', {id:'#id'},//parameters
{
update: {
method: 'PUT' // To send the HTTP Put request when calling this custom update method.
}
});
}
]);
And the controller code I have tried is:
self.checkUsersEntryDirection = function(){ //NOT WORKING
self.testuser = TestUser.get({ username: 'anton' }, function() {
console.log(angular.toJson(self.testuser));
}); // get() returns a single entry
}
The error I get is
Error in resource configuration for action get. Expected response to contain an object but got an array (Request: GET http://127.0.0.1:4001/api/testusers)
Notice how it didn't add on the where clause. I thought that any extra properties provided would be assigned as where clause items??
thanks

Using [] square brackets as part of a parameter in $resource GET call to API in Angular is not working

I am trying trying to GET user data from an ajax-localized REST api that wants parameters like so:
/api/activity?filter[user_id]=1
I have a factory set up with query parameters like so:
angular.module('app')
.factory('Activity',function($resource){
return $resource(ajaxInfo.api_url+'activity',
{ // Query parameters
filter: {
'[user_id]': '#userId'
},
},
{
'query':{
method:'GET',
headers: {
'X-WP-Nonce': ajaxInfo.nonce
},
isArray: false
}
});
})
I'm console.logging it in a template like so:
$scope.userOne = Activity.query({userId:1});
console.log($scope.userOne)
It's returning
http:site.dev/api/activity?filter=%7B%22%5Buser_id%5D%22:%22#userId%22%7D&userId=1".
Any idea what I'm doing wrong?
Here's what I did to fix this:
I created a factory called "CurrentUser" this factory basically returns the current user's object from an api.
Then I created a controller that passed the parameters to the Activity factory when I wanted to filter the activity by that user id.
$scope.userInfo = function(){
//call the CurrentUser and see if it's available and return it as u
CurrentUser.instance().then(function(u) {
//now query the activity factory and pass the filter as a string along with the user id as u.id
Activity.query({'filter[user_id]':u.id}, function(res){
$scope.userOne = res ;
console.log($scope.userOne);
});
})
};
$scope.userInfo();

AngularJS: Resource factory and callback function

Hi being new to Angular i'm having difficulty seeing how to handle data when using $resource in a factory. I'm trying to move from $http requests to $resources in my factory.
First i had (simplified code):
.factory('MetadataService', function($http) {
$http({
method: 'OPTIONS',
url: 'http://myurl'
}).success(function(data) {
customized_data = do_some_complex_handling_on_data(data)
callback(customized_data);
});
});
When i try to use a $resource in my factory, it seems that i have to call the do_some_complex_handling_on_data() method in my controller:
.factory('MetadataService', function($resource) {
return($resource('http://myurl', {}, {
metadata: {method: 'OPTIONS'}
}));
});
# controller:
var metadata = do_some_complex_handling_on_data(MetadataService.metadata());
Since i'm gonna use the factory in a lot of controllers for different sections in my application (that's why i made a factory in the first place), i would like to have my factory return the data as i need it. And not have to customize the data after the factory returns it.
question: How do i let my factory call the do_some_complex_handling_on_data() function instead of the controller?
You can use response transformer that $http service provides. A transformer is used to transform the response of $http before it is delivered to the end client.
By default there is a single transformer register that convert json string to json object. You can append your own transformer to this collection and it will be called with the response json object. In your transformer function you can then call any function you want that can transform the data.
metadata: {
method: 'OPTIONS'
transformResponse: appendTransform($http.defaults.transformResponse,
function(value) {
return do_some_complex_handling_on_data(value);
})
}
function appendTransform(defaults, transform) {
// We can't guarantee that the default transformation is an array
defaults = angular.isArray(defaults) ? defaults : [defaults];
// Append the new transformation to the defaults
return defaults.concat(transform);
}
I have taken this code from the docs here
Also read documentation on "Default Transformations" in $http service

Angular service, $http.get() with a route param?

Typically when asking the API endpoint for JSON, I'd write something like this:
factory('User', function($http) {
return {
get: function() {
return $http.get('/api/users');
}
}
});
However, how can I add a route parameter to get a specific user (RESTful show method)?
i.e. /api/users/1 to get user number one. But I want it to be dynamic based on the logged in user.
You can use the $resource factory instead of using $http. As stated in the documentation $resource is:
A factory which creates a resource object that lets you interact with
RESTful server-side data sources.
To do what you want, you can simply declare it like this:
factory('User', function($resource) {
var UserResource = $resource('/api/users/:id');
return UserResource;
});
Usage:
.controller('Ctrl', function($scope, User) {
// Sends GET /api/users/1
User.get({id: '1'}).$promise.then(function(user) {
// expects a single user data object
console.log(user);
});
// Sends GET /api/users
User.query().$promise.then(function(users) {
// expects an array of user data objects
console.log(users);
});
});

$resource Custom Action Replaces my Scoped Variable with the Server Response

I am using a $resource with a custom action.
myApp.factory('User', [ '$resource', function($resource)
{
return $resource('/QuantumServer/users/:id.json',
{
id : '#id'
},
{
resetPassword :
{
method : 'POST',
url : '/QuantumServer/users/:id/resetPassword.json'
}
});
} ]);
I can retrieve my User objects no problem. The problem is that when I invoke the custom action, the value of my locally-scoped User object gets replaced with the server response. This is a problem because the server response is { success : true }, which causes my local object to loose all its field values.
$scope.resetPassword = function()
{
$scope.userBeingEdited.$resetPassword(
{}, function(value, responseHeaders)
{
alert('Password reset');
// The value of $scope.userBeingEdited has been replaced with the
// server response - how to stop this from happening?
});
};
I know that the RESTful philosophy states that e.g. a POST to a resouce would update that resource (on the server) and then return a copy of the updated resource. I undertand that this is how AngularJS $resouce.$save works. But must it really apply to my custom actions?
This is one workaround that I'm aware of, which causes a copy of the object to be updated which we then discard. Is this the most graceful way?
$scope.resetPassword = function()
{
angular.copy($scope.userBeingEdited).$resetPassword(function(value, responseHeaders)
{
alert('Password reset');
});
};

Resources