How to pass in API subdomain to ngResource? - angularjs

I'm using ngResource to consume a RESTful API, and have implemented the following service:
app.factory('User', function($resource) {
return $resource('/api/users/:id', { id: '#id' });
});
I would like to pass in a subdomain to it. Is there a way to do this?
I'm aware of the following workarounds:
Pass in a full URL: api.acme.com/users/:id
Inject a variable on the url: `'api.' + mydomain + '/users/:id'
With that said, I believe it'd be cleaner to just send the subdoman as an argument. Can this be done?

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};
});

AngularJS $resource Headers POST

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';
}]);

AngularJs $resource, REST and Symfony2 FOSRestBundle

I am using the FOSRestBundle, this bundle generates routes for me and pluralises those routes. For instance a GET request to /users.json is different from a GET request to /user/15.json
Its worth noting that a call to /users/15.json fails.
More on this issue here https://github.com/FriendsOfSymfony/FOSRestBundle/issues/247
In my Angular app I use a $resource to create a RESTful call, the URL is a template as detailed here https://docs.angularjs.org/api/ngResource/service/$resource
For example
$resource('http://example.com/:id.json')
Or
$resource('http://example.com/user/:id.json')
And there in is the problem, the $resource seems to accept a single URL template for the REST resource, but I have multiple ones because of the forced pluralisation from the FOSRestBundle.
I do not think hacking the FOSRestBundle is the answer, so what can I do with my usage of $resource in AngularJs to correct this issue?
you can set url for every method as third parameter - actions
angular.module("example", ["ngResource"])
.factory("userService", function($resource) {
return $resource("http://example.com/user/:id.json", {
id: "#id"
}, {
'query': {
url: "http://example.com/users"
}
})
})
.run(function(userService) {
userService.query();
userService.get({id:1});
})

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.

Combining GET and POST as get and save in AngularJS service

I've got a service that gets details for a certain user profile:
.factory('UserDetails', function($resource, $rootScope) {
return $resource('../html/app/user_details.json', {}, {
query:
{
method: 'GET',
params: {},
isArray: true
}
});
})
I'm mocking the non-existent back-end with a plain JSON file for now.
I also need to be able to update the user profile - so I need to write a POST request (probably to the same end-point).
In my controller I currently use:
UserDetails.get({}, function(data) {
$scope.profile = angular.copy(data.user_details);
});
It would be elegant to be able to write
UserDetails.save({$scope.profile}, function(data){ /* .. */});
Is there a way to extend my UserDetails service to achieve this? How would I have to modify the service declaration?
You can use angular-mock for your purpouses.
See related Stackoverflow question

Resources