Can't get response from Angular $resource - javascript

I have a factory:
.factory('CompanyRolesResource', function($resource, FdConfig) {
return $resource(FdConfig.routes.companyRoles);
})
And I have a function that use this factory:
ctrl.saveCompanyRole = function(companyRole) {
return CompanyRolesResource.save({}, companyRole).$promise.then(function (response) {
console.log(response)
});
};
In Chrome DevTools I see that response is data like {status: 200, data: {...}}. But in console.log I just see:
Resource
$promise: Promise
$$state: Object
__proto__: Object
$resolved: true
Where is my data? I can't find it also inside of $promise and $$state.
UPD:
I get right response when I use this way:
$http({
url: FdConfig.routes.companyRoles,
method: "POST",
data: companyRole
}).then(function (response) {
console.log(response.data);
});
But my console.log(response) in factory returns undefined.

You can't access your data from $resource directly as it is retrieved from server asynchronously. This means that your data isn't yet loaded when you try to access it. What you need to do is to supply callback for $resource action.
Starting from Angular 1.2, $resource provides you $promise for each action which you can use to retrieve your data when it's loaded:
CompanyRolesResource.save({}, companyRole).$promise.then(function (response) {
// do whatever you want with your response.data here
});

Resource is your data object. When you use $resource, you don't get the response as (status, data, headers, config) Object. You will directly get the response (your expected response data)

It is important to realize that invoking a $resource object method immediately returns an empty reference (object or array depending on isArray). Once the data is returned from the server the existing reference is populated with the actual data.
Under the hood, the ngResource API uses angular.copy to copy the server data to the empty reference. If the data is not a JavaScript object, nothing will be copied.
In the case of the .save action method, if an array is returned, a $resource:badcfg error will be thrown.
Error: $resource:badcfg
Response does not match configured parameter
Description
This error occurs when the $resource service expects a response that can be deserialized as an array but receives an object, or vice versa. By default, all resource actions expect objects, except query which expects arrays.
To resolve this error, make sure your $resource configuration matches the actual format of the data returned from the server.
For more information, see the $resource API reference documentation.
— AngularJS $resource:badcfg Error Reference

Related

Can someone walk me throu the angular code

webApp.factory('userAPIService', ['$resource',
function ($resource) {
return $resource(
"/api/reportconfig/:Id",
{Id: "#Id" },
{
// at some point change methods from GET to POST and DELETE
"update": {method: "PUT"},
"getreport": {'method': 'GET', 'params': { Id:'getReportbyReportID', expire: 'true', cache:'false'}, isArray: true},
"createreport": {'method': 'GET', 'params': { Id:'createreport', expire: 'true', cache:'false'}},
"listreport": {'method': 'GET', 'params': { Id:'listreport', expire: 'true', cache:'false'}, isArray: true},//requre user_uuid
"deletereport": {'method': 'GET', 'params': { Id:'deletereport', expire: 'true', cache:'false'}}
}
);
}]);
The above code get called with the following command
userAPIService.createreport({
'report_config_json': report_config_json, topic_uuid: topic.uuid, report_id: reportID, user_id:userid }, {'Id': 'createreport'})
I'm having a hard time understanding what the userAPIService actually returns when called, an object? what does it return when I call userAPIService.createreport? How/when are the arguments passed to it?
With only the limited information I have above, here is what I believe is taking place in your code:
First, you are creating a factory, which is similar to a service, except you get multiple instances as opposed to a singleton (a one-time creation that every module can get via injection)
When you use the userAPIService factory in your code, you are being returned a function (which in this scenario could act like a constructor.) I can't tell without seeing the context of your use of userAPIService, but I would assume you are creating a local variable called 'userAPIService' which is being initialized to the results of a call to userAPIService().
At this point you have an instance of a userAPIService which appears to just be an data retrieval service (not to be confused with an Angular Service, which is a singleton)
your call to userAPIService.createreport() will initially return an empty object or array (noted in the docs at the bottom of this answer.) it will then make the specified $http call to the URL (from $resource definition) via the Method (from the $resource definition) and attempt to retrieve the data you are looking for. Once it has completed that request, it will then populate the reference that was just created with the actual data returned.
Since your factory creates custom actions to be taken via $resource we will look at that definition to determine what will take place when you call .createreport():
"createreport": {'method': 'GET', 'params': { Id:'createreport', expire: 'true', cache:'false'}}
This line tells $resource how to handle requests using the createreport() method. It says that when this method is called, it will make a request to the $resource object's URL via GET. It will pass default values of expire:true and cache:false as well as Id:'createreport' which will be used to populate the URL (Unless an Id is specified in your method call - which it is), since it requested an Id object via :Id at the end.
Now, when you made the actual method call, you specified two objects to pass to the $resource request, the first will then be used to basically override the default parameter values that were specified when you create the $resource method. The second will be passed as headers along with the $http request that $resource will then make.
For even more information, I would highly recommend that you read the documentation: https://docs.angularjs.org/api/ngResource/service/$resource

$Resource error - when using $save.success callback but data is saving OK

I'm trying to use a resource to save some data, and am getting something strange happen:
here is the code:
var appointment = new Appointment(formData);
console.log(appointment);
appointment.$save().success(function (data, status, headers, config){
console.log(data);
$state.transitionTo('form.success');
});
now the wierd thing is that the data is saving so the $save function is working, but I'm getting undefined is not a function errors, and the success callback isnt working - does anyone know why?
The resource for the Appointments is:
angular.module('MyApp')
.factory('Appointment', function($resource){
return $resource('/api/admin/:id', { id: "#_id" }, {
query: {method:'GET', isArray:true}
});
})
and I'm using this and its inherent $save function, so it shouldn't be a problem - also it seems to be the callback thats not working - the save is adding data no problem
SOLUTION:
I simplified it by just doing:
appointment.$save(function(data){
//stuff here for the callback works
});
also I think that using the promise method .then would work, but I didn't try it.
I marked it as accepted anyway for good karma!
Thanks
The success function is specific to the $http service:
The $http service is a function which takes a single argument — a configuration object — that is used to generate an HTTP request and returns a promise with two $http specific methods: success and error.
The $save method returns a regular promise, so you can use then instead:
appointment.$save().then(function (data, status, headers, config){
console.log(data);
$state.transitionTo('form.success');
});

AngularJS HTTP Resource - Response Function Undefined

I'm using an Angular HTTP Resource to get some data from an API. The method on the API is actually a PUT, but returns an array of data. (Note, it's not my API)
It performs the HTTP Call perfectly and I can see in the Network on Google Developer Tools my response is right. However, I keep getting "TypeError: undefined is not a function" when trying to work with the response data.
Here are some of the different methods I've tried and each one gives the same TypeError:
HTTP Resource
.factory('Sports', ['$resource', 'SPORTS_CONFIG',
function($resource, SPORTS_CONFIG) {
return $resource(SPORTS_CONFIG.URL, {}, {
get: {
method: 'PUT',
isArray: true
}
});
}
])
Angular JS Attempts
// Construct Sports Body
var s = new Sports($scope.sport);
// Attempt 1
s.$get({}, function(data){
});
// Attempt 2
s.$get({}).then(function(data){
});
// Attempt 3
s.$get({}).$promise.then(data){
});
EDIT
After looking at my error code more, it looks like the error is occurring on 'isArray' in my HTTP Resource. When I set isArray to false, it errors because it expects an object but gets an array. When I keep it true, it errors and says TypeError: undefined is not a function. When I click the javascript line it's 'isArray'.
SECOND EDIT
I've gotten it to work using the following code:
$scope.teams = Sports.get($scope.sport);
However, $scope.teams = [0, $promise, $resolved] . How can I only get [0] instead of the $promise and $resolved?
the argument to your 'then' function should itself be a function.
eg:
s.$get({}).then(function (data){
});
Your syntax looks wrong, follow this approach instead:
$http.get('/someurl').then(function(response) {
//do something with response.data;
}, function(errResponse) {
console.error('Error while fetching data');
});
As you can see you should be passing in a function which passes in the response from the server, and then you can get at your data.
You can try something like this (with a function)
$http({
method : "GET",
url : "your_url"
}).success(function(data, status, headers, config) {
$scope.yourVariable= data;
}).error(function(data, status, headers, config) {
alert("Request failed. HTTP status:" + status);
});
Due to the edit above, this answer became outdated.
As I cannot comment right now, the way to get the just first item as you'd like is simple:
$scope.teams = Sports.get($scope.sport)[0];

how to get correct JSON object from flickr API

I used flickr photo search method to retrieve public photos.
when I run it with jquery, it works fine, I get the json object in correct form.
{
"photos": {
"photo": [
{
.........
}
]
},
"stat": "ok"
}
But when I use it with AngularJs, I got the same object with a prefix jsonFlickrApi
jsonFlickrApi({
"photos": {
"photo": [
{
......
}
]
},
"stat": "ok"
})
what I used in AngularJs is:
myApp.service('dataService', function($http) {
delete $http.defaults.headers.common['X-Requested-With'];
this.flickrPhotoSearch = function() {
return $http({
method: 'GET',
url: 'https://api.flickr.com/services/rest/?method=flickr.photos.search&api_key=3f807259749363aaa29c2fa93945&tags=india&format=json&callback=?',
dataType: 'json'
});
}
});
Please tell me how can I convert the second JSON to the first one.
Is there anything I can do in $http call or have to alter JSON object.
There was problem in the url.
This Url works for me.
https://api.flickr.com/services/rest/?method=flickr.people.getPublicPhotos&api_key=3f807259749363aaa29c712fa93945&user_id=61495424#N00&format=json&nojsoncallback=?
You have to add nojsoncallback=1 to the url, like this
https://api.flickr.com/services/rest/?method=flickr.photos.getRecent&api_key=XXX&format=json&nojsoncallback=1
And that remove the jsonFlickrApi function on response.
The above answer which says to add nojsoncallback=1 is correct, but I'd like to provide more context and reasoning behind it.
If you take a look at the documentation (which is poorly formatted in my opinion): https://www.flickr.com/services/api/response.json.html and scroll all the way to the bottom you will find, tucked away:
Callback Function
If you just want the raw JSON, with no function wrapper, add the parameter nojsoncallback with a value of 1 to your request.
To define your own callback function name, add the parameter jsoncallback with your desired name as the value.
nojsoncallback=1 -> {...}
jsoncallback=wooYay -> wooYay({...});
The key part being: If you just want the raw JSON, with no function wrapper, add the parameter nojsoncallback with a value of 1 to your request
Therefore, add this to your request and it will remove jsonFlickrAPI wrapper that you are seeing in your response: nojsoncallback=1
You are getting a JSONP response (notice the P) which is basically a function call with an argument that is the response you are expecting.
Easy solution for you: Create a function named jsonFlickrApi with a parameter response and you can do your handing in there.
At this point, I am not sure if you can define your function inside your service but try it. If not, you can define it outside.
Alternatively, try using $http.get function instead. Were you specifying the return accepted by the client in your jQuery original code?
EDIT
Try this setting the data type of the request using $http or $http.get without forgetting to specify the data property in the settings object.
$http({
url: 'http://localhost:8080/example/teste',
dataType: 'json',
method: 'POST',
data: '',
headers: {
"Content-Type": "application/json"
}
}).success(function(response){
$scope.response = response;
}).error(function(error){
$scope.error = error;
});

Backbonejs simplest collection fetch

I'm trying to download, parse and show a list, from the XML received from my server using Backbone.js. The code is like:
var Item = Backbone.collection.extend({
url: "http://myurl.com/file.xml",
parse: function() {
console.log("parse");
},
success: function(data) {
console.log(data);
},
error: function() {
console.log("error");
}
});
var View1=Backbone.view.extend({
initialize: function() {
var item = new Item();
item.fetch();
}
});
When I check it in the Chrome extension, the XML file is getting downloaded but the breakpoints placed in the parse, success, error directly lands to the error.
And it has 3 arguments, but I'm unable to extract any information from that.
Backbone does not support fetching XML, hence, you'll need to override the sync method to provide your own custom parsing functionality. If you don't want to have to mess with Backbone internals, try doing your $.ajax GET first, parse your response into a proper JSON Array and then use that array with a Backbone#Collection-reset.
Backbone#Collection-fetch
The server handler for fetch requests should return a JSON array of
models.
Backbone#Sync
With the default implementation, when Backbone.sync sends up a request
to save a model, its attributes will be passed, serialized as JSON,
and sent in the HTTP body with content-type application/json. When
returning a JSON response, send down the attributes of the model that
have been changed by the server, and need to be updated on the client.
When responding to a "read" request from a collection
(Collection#fetch), send down an array of model attribute objects.

Categories