How to get a where clause using ngResource in angularJS - 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

Related

How to contact a non-standard API using Angular ngResource

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

AngularJS : Service for data between controllers

I have a page with a main controller and a nested controller for showing details about a product. I want to use a a service in angular to call the server, retrieve a data object and hold that data object. The main controller will call the service to fetch the data and the details controller needs to know it was updated and then access the data. My service looks like this:
.service("productService", function ($http, $q) {
var product = {};
//interface that is returned
return ({
fetchProduct: fetchProduct,
clearProduct: clearProduct,
product: product
});
function fetchProduct(ID) {
var request = $http({
method: "get",
url: "/online/productdata.ashx?itemID=" + ID,
params: {
action: "get"
}
});
return (request.then(handleSuccess, handleError));
};
function clearProduct() {
product = {};
};
// Transform the error response, unwrapping the application dta from
// the API response payload.
function handleError(response) {
// The API response from the server should be returned in a
// nomralized format. However, if the request was not handled by the
// server (or what not handles properly - ex. server error), then we
// may have to normalize it on our end, as best we can.
if (
!angular.isObject(response.data) ||
!response.data.message
) {
return ($q.reject("An unknown error occurred."));
}
// Otherwise, use expected error message.
return ($q.reject(response.data.message));
};
// I attempt to transform the successful response and unwrap the application data
// from the API response payload.
function handleSuccess(response) {
product = response.data;
console.log("Found Data: " + angular.toJson(response.data))
return (response.data);
};
})
In my main controller I set a scope object to the service like this:
$scope.SelectedProduct = productService;
When the user clicks the button to show the product it is called via the $scope handle:
$scope.SelectedProduct.fetchProduct(ID);
The details controller has the same assignment for the $scope.SelectedProduct. I am new to using services but what I understood is that angular would bind to the service object and changes to the property product would trigger binding to any updates. That is not happening - in fact I do see the data after the fetch operation. In the service I have a console.log on the returned data and it is showing the correct data. However the product property is not getting updated. Can someone tell me what I am doing wrong please? Neither controller has access to the data after it is fetched. I understand that I am getting back a promise but the data is never there even after a timeout check.
Try it with a factory instead of a service.
AngularJS: Factory vs Service vs Provider

Angular : intercept specific request with $resource

I'm new to Angular, and am working on an interceptor. I created an angular factory to get some data from an API like that :
app.factory('Connection',['$resource',function($resource) {
return $resource('url',{param1: '1',param2: '55'},);
}]);
I also created the interceptor which looks like that :
app.factory('connectionInterceptor', function($q,$location) {
var connectionInterceptor = {
response: // code here
responseError: // code here
};
return connectionInterceptor;
});
The interceptor works well. But it intercepts every http request I do, and I'd like to make it work for a specific $resource. I read in angular $resource doc that there is a way to make it by adding an interceptor action/param to $resource. So I tried :
app.factory('Connection',['$resource',function($resource) {
return $resource('http://localhost:8080/api/login',{user: '1',password: '55'}, {},
query: {
method : 'GET',
interceptor : 'connectionInterceptor'
}
});
}]);
which didn't work. The thrown error is : Error in resource configuration for action query. Expected response to contain an object but got an array.
What did I miss ?
As you said, interceptors are globally set. I had to add a test to my response to check the $resource URL and add some specific treatment.
module.factory('interceptor', function() {
var interceptor = {
response: function(response) {
if (response.config.url.startsWith('my url')) {
// some treatment
}
else
// other treatment
return response;
}
return connectionInterceptor;
});

Angularjs $resource, how do I know which obj is being passed to it? URL not receiving :id

I am using a MEAN stack and I am a little confused on how the $resource works. I understand that the $resource factory is a service that retrieves data for controllers. However, I have two model objects, Compositions and Critiques. What I am trying to do is get critiques based off the url, which looks something like this: /compositions/:compositionId/review.
For some reason whenever I call
Reviews.query(function(review) {
console.log(review);
$scope.reviews= review;
});
I get this error:
GET localhost:3000/compositions/review 500 (Internal Server Error)
Here are my services:
angular.module('mean').factory('Reviews', ['$resource',
function($resource) {
return $resource('compositions/:docId/review', {
docId: '#docId'
},
{
update: {
method: 'PUT'
}
});
}
]);
angular.module('mean').factory('Compositions', ['$resource',
function($resource) {
return $resource('compositions/:compositionId', {
compositionId: '#_id'
},
{
update: {
method: 'PUT'
}
});
}
]);
The second one works if I navigate to /compositions/:compId, but the first one does not. Instead I get the error above. Why isn't the docId being passed in? Any ideas?
I want the compositionId, which is the docId in the 'critique' object models terms, but I want to get back critique objects. What am I doing wrong? Any help or advice is appreciated, thanks!
You are passing callback to query() - that is wrong. You should pass there a params object with your docId. This is how you should do that (in Angular 1.2)
Reviews.query({docId: 5}).$promise.then(function(review) {
console.log(review);
});

$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