AngularJS $resource Headers POST - angularjs

I would like to know how to pass headers to AngularJS $resource method
Here is the factory method
.factory('DataRepository', function ($resource) {
return $resource(serviceUrlPrefix + '/api/v1/AppList/:id', { id: '#id' }, { 'query': { method: 'GET', isArray: false }, 'update': { method: 'PUT', AppList: '#req', headers: { 'X-Requested-With': 'XmlHttpRequest' } } });
});
Here is the call to the dataRepository
dataRepository.update({ id: req[uniqueIDColumn] }, req, function (data) {
},
function (error) {
});
This code works fine. But i have few queries
Question 1:
Rather than specifying the headers in the factory method , how can i specify it in the call to the factory method? I tried few methods but it didnt work out.
Question 2:
I specified the header in the update method in the factory. When i perform "Save" using that factory, that header has been taken by default. But i have specified it explicitly for PUT method. Right? Why and how?
Question 3:
If i would like to specify the header for the particular factory in common for all Http methods, what is the way to do it?
Question 4:
What is the nomenclature for passing the parameters and the significance of "#" symbol before parameter and also in the below part, AppList is the parameter name used in the WebAPI, is it mandatory that it should match the parameter name in the WebAPI method, if its not matching, its not working:(
AppList: '#req'

I'm afraid we don't use $resource, but it does depend on $http. We configure the header with the below. Not sure about the rest of your questions.
I will say that we also do not use $http directly. We created our own "requestHelper" service that we inject everywhere. That allows us to inject things before making calls to $http as well as catch the response before passing the result on to the real caller. Helps with common error handling.
Configure headers for $http:
module.config(['$httpProvider', function ($httpProvider) {
$httpProvider.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
}]);

Related

Store domain in one place in angular js service

I have the following example method in angular service:
function send(data) {
return $http({
method: 'POST',
url: 'https://test.domain/test/send',
data: $httpParamSerializerJQLike(data)
});
}
The domain that is https://test.domain/test is the same for all the services in my app. I do not want to write it every time in every services. I can abstract it in a constant and inject it in every service but I wonder if there is more clever solution. Is it possible to store the domain part in an interceptor or any other suggestions are welcome. Please provide code examples as I am quite new to angular. Thanks
I'd say rather than abstracting the values out into a constant, you should abstract the $http call into a service. Then you can just inject that service into all of your other services in place of $http. For example:
angular.module('myApp').factory("myHttp", ["$http", function ($http) {
return function (config) {
config.url = "https://test.domain/test" + config.url;
return $http(config);
};
}]);
So effectively what this service is doing is proxying calls to $http, but prepending your common URL to the beginning - this would allow you to change your example code to:
function send(data) {
return myHttp({
method: 'POST',
url: '/send',
data: $httpParamSerializerJQLike(data)
});
}
Of course, this is just one example of how you could do an abstraction like this - the myHttp service could take any form you like, depending on what would be most convenient for you. I think this is a better solution than using an interceptor in this case, as it allows you to pick and choose when you use it, rather than it being applied to every single HTTP request.
create an interceptor and on requests change the url.
angular.module('app').factory('domainInterceptorService', [
function () {
var request = function (config) {
config.url = 'https://test.domain/' + config.url;
}
return config;
}
return {request: request};
});

Angular - correct approach to handle the data fetch from server?

Assume that, I am using the angular-resource - module with my ng-app. I don't able to understand the data handling easy and scale able way.. any one give me / show me a correct way to answering all this questions?
a) Generally how to fetch data from url in the angular.?
b) in case each of the controller may require different url and data if so how the fetch process added on each of controller.?
c) or need we make a service to provide the data according to the controllers parameters - if so how to pass parametes to service?
d) All above have GET, PUT and DELETE, 'POST` then how to handle all them - is all this need separate services?
Thanks in advance.
Use angular-resource as you said within a service/factory. It already provides a lot of your requirements:
myApp.factory("dataService", [
"$resource",
function ($resource) {
return $resource("http://someBaseUrl/:action/:id", {
id: "#id" // default parameters
},
{
// custom methods
update: { method: "PUT" },
doOtherStuff: { method: "GET", action: "DoOtherStuff" }
});
}
]);
The $resource default provides for the following REST compliant functions:
{
'get': {method:'GET'},
'save': {method:'POST'},
'query': {method:'GET', isArray:true},
'remove': {method:'DELETE'},
'delete': {method:'DELETE'}
};
Any other functions you have to include yourself, like the update and the doOtherStuff in the example above.
The :action part is an easy way to provide any custom action, that is not REST compliant.
Usage in controllers:
myApp.controller("myCtrl", [
"dataService",
function (dataService) {
// first parameter can be used for any extra query parameters
// second parameter always is a callback
var myData = dataService.query({}, function() {
// success
});
var mySingleInstance = dataService.get({ id: 12 });
this.doUpdate = function (entity) {
dataService.update(entity);
// Or, if the 'entity' is a resource entity:
// entity.$update();
}
this.customMethod = function () {
dataService.doOtherStuff();
}
}
]);
See https://docs.angularjs.org/api/ngResource/service/$resource for the full documentation

$http(config) vs $http.get(...): What is the difference?

According to the Angular documentation for $http, it seems that the constructor
$http(config)
and the functions
$http.get(...)
both return the same things - HttpPromises.
So what is the difference between them? Or are they just two ways to write the exact same thing?
$http.get(...), as said in the doc you gave link to, is a shortcut method to perform GET request. You won't be able to make any other type of request with $http.get - GET only. Note that POST, PUT, HEAD and DELETE have their corresponding shortcut methods too.
All these methods, however, are essentially the $http(config) calls - with method parameter pre-specified. Here's how it's done (1.3.6 source):
createShortMethods('get', 'delete', 'head', 'jsonp');
// ...
function createShortMethods(names) {
forEach(arguments, function(name) {
$http[name] = function(url, config) {
return $http(extend(config || {}, {
method: name,
url: url
}));
};
});
}
Still, sometimes it's more convenient to use $http(config) syntax - for example, if one has to choose the request method based on some external conditions that should be easy to switch. Note that if you don't specify method property in config, GET is used:
function $http(requestConfig) {
var config = {
method: 'get',
transformRequest: defaults.transformRequest,
transformResponse: defaults.transformResponse
};
// ... some checks skipped
extend(config, requestConfig);
}

Passing a path with '/' to $resource or $http factory

Is there a way to pass a parameter containing / to Factory? Want to accomplish something like
.factory('MyData', ['$resource', function ($resource) {
return $resource('http://1.2.3.4/:urlFragment', {
urlFragment : '' // default empty
}, {
getData : {
method : 'GET'
},
And calling it
$scope.scopeVar = MyData.getData({urlFragment : '/some/path/to/data'});
Looking at the network console, I see that / are replaced with %2.
Can I encode the passed parameter inside Factory? (Using $http or $resource).
Or in general, how can I execute any functions on parameters inside factory?
No, you can't really get access to the url inside of your factory because $resource automatically handles it. But thankfully Angular gives you a way to get access to the url before it is called by using the $resource directly. Looking at the docs here, one of the actions you can supply in your $resource declaration is a transformRequest property.
return $resource('http://1.2.3.4/:urlFragment', {urlFragment: ''}, {
getData: {method: 'GET', transformRequest: function(data, headers){
// make your modifications here to either data or headers
}}
});
Although I haven't actually run this code, I believe that should allow you to do what you want. Let me know if it doesn't.

AngularJS $resource save() causes HTTP Error 415 (Unsupported Media Type)

I am using Angular 1.2-RC2 (also tried 1.0.8 and 1.1.x) and the ngResource module. The backend is a Spring WebMVC application.
angular.module("dox", ['ngResource'])
.controller('SettingsController', function ($scope, Settings) {
$scope.settings = Settings.query();
$scope.save = function () {
Settings.save();
};
})
.factory('Settings', function ($resource) {
return $resource('/api/v1/settings/:settingId', {settingId: '#id'}, {
'save': {
method: 'POST',
headers: {
'Content-Type': 'application/json'
}
}
});
});
Whenever the save() method on the Settings class gets called the frontend receives a HTTP 415 (Unsupported media type). The reason is that AngularJS send the POST request using the following content type:
Content type: text/plain;charset=UTF-8
but the backend expects
Content type: application/json;charset=UTF-8
According the API docs it should be possible to override the header but my settings are somehow ignored. I seems that this is a common problem and as a workaround there are many recommendation to use $http.post instead of $resource.
Can you give me any hint how to solve this content type problem using the $resource service?
Please find the backend controller code here.
First, you're overriding a built-in $save method, so you can just omit the save: part (see source code). If you do define additional HTTP methods that aren't built-in, you can update the $httpProvider like so (this is to add the patch method):
.config(['$httpProvider', function($httpProvider) {
$httpProvider.defaults.headers.patch = {
'Content-Type': 'application/json;charset=utf-8'
}
}]);
Kevin Stone pushed me to the right direction. Thank you!
Since query() returns an array and save() is meant to save only one item of that array at the same time I had to reimplement the save() stuff differently.
$scope.save = function () {
angular.forEach($scope.settings, function (value, key) {
value.$save();
});
};
Done! Again thank you for your hints and help

Resources