I'm using Angular to consume a RESTful API on the same application. I have a $resource setup for the contacts resource at http://sample-site.com/api/contacts
This is great and it works, however I need to interact with the basic CRUD of /api/contacts on different pages of the application.
For example, I need to interact with contacts again at another page on web app hosted at http://sample-site/friends/{friend-id}. However when I try to use my contact resource on that page, the url to the resource is appended to the current URL:
GET | http://sample-site/friends/1/api/contact
but what I really need is to GET | http://sample-site/api/contact on that resource on that page.
Is there a way to configure a resource to define a different base URL other than in relation to the current page?
This is my attempt to change the base URL inside the resource:
.factory('ContactRest', ['$resource', '$location', function($resource, $location) {
var host = $location.host()
return $resource('https://:url/:action', {}, {
// Normal CRUD actions
query: {
url : host,
action : 'api/contact',
method : 'GET',
isArray : true,
}
}]);
Which makes https://sample-site/friends/1/sample-site/api/contact. Regardless of how I define the $resource, just keeps appending any URL's to the base URL. I need to change the very base of the URL.
I got it!
.factory('ContactRest', ['$resource', '$location', function($resource, $location) {
var host = $location.host()
return $resource('http://' + host + ':action', {}, {
// Normal CRUD actions
query: {
method : 'GET',
isArray : true,
}
}]);
/**
* In controller
*/
ContactRest.query({ action: 'api/contact' }, function(contact) {
console.log('Got it, take that Havascript!');
});
Related
I'm trying to create a product browser. I wrote simple HTML view code with a text field, button and result list. I also wrote REST API GET method with the parameter which query objects by ID. Url of my view is #/Products but REST method URL #/Products/Id
REST GET
#Path("/{id:[0-9][0-9]*}")
#Produces("application/json")
public Response findById(#PathParam("id") Long id) {body}.
Now I'm trying to write controller to #/Product view
angular.module('searchingPage').controller('SearchProductsController', function($scope, $http, $filter, ProductResource ) {
$scope.search={};
$scope.performSearchById = function() {
//goal $scope.searchResults = ProductResource.findById($scope.search.id);
};
})
How can I call my REST API with parameter and right path with Id in it?
the '#' sign use for client side not server side, your rest method url is probably something like "api/Products/Id". you can simply call rest method as below
$scope.performSearchById = function() {
$http({
url: 'api/Products/' + $scope.search.id,
method: 'GET'
}).then(function(data){
$scope.searchResults = data.data;
})
};
}
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};
});
I'm trying to get current user coordinates and afterwards send them as a parameter of http request and parse response.
Workflow is next -> user opens view, (loader shown) - coordinates are retrieved (if not send request without coordinates) - send requests - parse and display response - hide loader.
What is the best way to achieve this?
I have tried to create two services, to retrieve coordinates using navigator.geolocation.getCurrentPosition, but I'm unable to return promise in which i would send http request using $http.get.
This workflow should be used in different controllers so I'm searching for a way which code will be most reusable. Thanks!
Update: this is a code sample of how I did resolve waiting for $http to complete before view is shown, but I have no idea how to use same approach with navigator.geolocation as it is not returning a promise.
.state('tab.explore.index', {
url: '',
templateUrl: 'templates/tab-explore.html',
controller: 'ExploreCtrl',
resolve: {
explore: function ($stateParams, Explore) {
console.log("rr");
return Explore.explore();
}
}
});
Service:
.factory('Explore', ["$http", "ApiEndPoint", "Resort", "ServiceTypes", function ($http, ApiEndPoint, Resort) {
return {
explore: function () {
console.log("loc");
**//somehow somewhere here should code wait to retrieve coordinates and send them as url parameter**
var url = ApiEndPoint().explore + Resort.id;
return $http.get(url);
}
}
}]);
controler:
.controller('ExploreCtrl',function ($scope, $stateParams,ServiceTypes,explore) {
console.log(explore.data.Services);
$scope.serviceTypes = ServiceTypes;
$scope.explore = explore.data;
})
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});
})
I have a basic factory returning a $resource called User:
angular.module('appServices').factory('User', [
'$resource',
function($resource){
return $resource('http://localhost:3000/users/:username', {username:'#username'});
}]);
In my UserController.js file I try to do something fairly simple:
angular.module("myApp").controller('UserController', ['$scope', '$routeParams', 'User',
function($scope, $routeParams, User){
var user = new User({email:'user#example.com', username: 'johndoe', password: 'mySecurePassw0rd!'});
user.$save();
}]);
I expect the $save() function to make a POST request to /users, however in the console I get http://localhost:3000/users/johndoe 404 response, because the route is obviously not set up on the server for POST requests with the username parameter appended...
Why is it that it does so in my code sample ? From the examples I have seen on the internet, the $save() function does not take into account the username and should directly POST to /users in my case.
Any help would be appreciated!
EDIT
I think I got the error (as always, immediately after posting the question on SO...)
It is probably because of the default parameter {username: "#username"} I specified in the $resource, as it expects there to be a username parameter by default ?
So the correct way to do it would be to return this resource from the factory:
return $resource('http://localhost:3000/users/:username');
correct ?
Username is a natural primary key. Unless you use switch to a surrogate one (generated on server side), you will need two different methods for entity creating and updating:
var User = $resource(
'/users/:username',
{
username: '#username'
},
{
save: {
methods: 'POST',
url: '/users'
},
update: {
method: 'PUT'
}
}
);