mgonto / restangular Goto Github PK
View Code? Open in Web Editor NEWAngularJS service to handle Rest API Restful Resources properly and easily
License: MIT License
AngularJS service to handle Rest API Restful Resources properly and easily
License: MIT License
I think there should be an easy way to assign methods to a resource that doesn't involve a bunch of hooking and if-statements. For instance as a second argument to .all(), like so:
Restangular.all('orders', prototype);
or perhaps as a configuration option to prevent duplication:
RestangularProvider.setInheritsFrom('orders', prototype);
This can be used for getters/setters when dealing with more complex data types (Dates, for instance) and other convenience methods.
Forgive me if there's already a decent way of doing this.
If the id of an entity is 0, then the test at line 61 will fail and the behaviour will not be the expected one.
If a user has a "what" param in its request, at this line : https://github.com/mgonto/restangular/blob/master/src/restangular.js#L246, it will clash wit Restangular hard-coded param.
Would be good to have it in the configurable fields, like "id", "route", ...
I just started using Restangular and I find it so much easier to use and configure than using $resource by itself. Due to the API I'm calling being parameter-based instead of path-based, I would like to create a URLCreator to make this easier to use. I've looked at the code and the suggestions in #42 and think I would be able to make this, but I'm not sure exactly what I need and where it needs to go (still fairly new to Angular).
Could you provide an example or guidance on how a custom URLCreator would be implemented?
Thank you for this great project!
RestangularProvider.setBaseUrl('http://localhost:8080/');
...
var postsRoot = Restangular.all("posts/");
postsRoot.getList()
Requests are issued to
http://localhost/posts
Instead of
http://localhost:8080/posts
Hi, thank you for Restangular! It's great and I love it.
But I have one problem.
I try to get the response from the server, with the new created Object and ID, but it didn't work:
var newObject = {"text":scope.newTodo,"date":attrs.day,"position":10};
scope.todos.post(newObject).then(function(data) {
scope.todos.push(data)
});
So far, parameters used by Restangular like "id", "route" and "parentResource" are hard-coded and might conflict with user params or not be the one exception (using _id in MongoDB for example).
Would be cool to have a way to customize the name of those parameters when initialization Restangular.
Add the ability to post new information to a model. For example, you can create a Building to an account by doing:
var newBuilding = {
name: "Gonto's building"
}
account.post("Buildings", newBuilding);
Hi,
How can be restangular used with resolve from the routeProvider?
Thanks
I think you should not use elem.delete in line 96 because its a keyword in js .. im trying your script in a play2 application and the (closure based) asset compiler compains about ... i renamed it to _delete ....
If I configure restangular to use the baseUrl http://localhost:8080, it removes the 8080 when it queries on the rest api. Is there a way I can force it to use port 8080?
Many thanks for this nifty piece of software. Exactly what I was looking for!
We are about to craft our own REST api and considering using HAL (http://stateless.co/hal_specification.html) for representation of resources. Would you see Restangular fit for purpose in this case? In particular, how would you traverse a tree following a "_link"? Also how would you access an "_embedded" in a slick way?
BTW I tried a few times to post on your blog but somehow didn't work.
Based on issue #34 but to implement with Promises support.
The natural seeming way to enable cache is something like:
app.config(function($httpProvider, $cacheFactory) {
$httpProvider.defaults.cache = $cacheFactory('myCache');
});
But that doesn't work, as $cacheFactory
is not a provider but a service.
A workaround is to wrap Restangular in another service, and inject $http
and $cacheFactory
into that service, and run $http.defaults.cache = $cacheFactory('myCache')
in there. Not ideal.
Need a way of enabling cache in RestangularProvider.
When I call my REST API for Users, I get following response:
{
meta: {
idx: 2,
total: 123
},
users: [
{id: 1, name: 'txi'},
{id: 2, name: 'tom'},
{id: 3, name: 'sam'},
{id: 4, name: 'vix'}
]
};
Basically along with the collections, I get few other properties (query object, pagination etc for example). How do one use Restangular for such scenario where the collection is the property of a response object? I do not want to extract the collection using ResponseExtractor because I'll also need other properties from the response object.
Add Restangular to cdnjs
First thing first, thx for this great project.
Yet, I'd really like Restangular to provide some form of request interceptor.
I need it because I have to strip some fields from the Restangular resource before I send it on the wire.
While converting from $resource to Restangular, I came across an issue. When using angular.copy on a Restangularized object, modifying the copy, then doing a .put on the copy, the .put sends the old data. Should I be copying the object in a different way or is this a bug?
Restangular.one('thing', id).get().then(
function(thing) {
// thing.name is "Old Name"
var thingCopy = angular.copy(thing);
thingCopy.name = "New Name";
thingCopy.put(); // Puts thing.name as "Old Name"
}
);
In many cases "uncommon" HTTP methods such as PATCH and DELETE are not usable, such as when behind a load balancing proxy (in particular AWS's Elastic Load Balancer). A workaround is to use a POST request with an X-HTTP-Method-Override header set to the desired "real" method.
It'd be nice to have a config option that not only enables this feature but can have an array of methods to use the override on. Something like:
angular.module('myModule', [Restangular])
.config(function (RestangularProvider) {
RestangularProvider.methodOverrides(['PUT', 'PATCH', 'DELETE']);
});
I have a usecase to load the data from templates through yaml file. The data from yaml file belongs to many parent's and it's child resources, this would require again to post it to non restful actions. i am new to angularjs and advanced javascript, can you please let me know how to achieve this in restangular or any feedback you have.
Hi,
I'm working on an AngularJS project with unit tests. All those tests work fine except I add the restangular.js file in the files property in the karma.conf.js.
I've got this sort of error:
TypeError: Property 'module' of object [object Object] is not a function
When I remove the restangular.js file declaration in the Karma conf, all work again.
Note: My current tests don't use any Restangular function yet.
I have an API that allows for pagination of collections. So for /apiv1/albums/1/page=1&pageSize=10, the result can be
{
data:[{id:1, name:'christmas photos'}, ....]
paging: {offset: 0, totalItems:200 }
}
Given the way the responseExtractor works, there seems to be no way to preserve the paging information. Note that the api is called with getList.
Curious if this is meant to only handle the actually http requests, or if it handles caching.
If not, is there a way to hook into the http requests to intercept and write a caching plugin for it?
backend runs at http://localhost/drupal_rest/api/v1
frontend is a yeoman/angular app at http://localhost:9000
module config:
angular.module('ngResttestApp')
.config(function(RestangularProvider) {
RestangularProvider.setBaseUrl('http://localhost/drupal_rest/api/v1');
});
controller:
angular.module('ngResttestApp')
.controller('MainCtrl', ['$scope','Restangular', function ($scope, Restangular) {
var nodes = Restangular.all('node');
nodes.getList().then(function(nodes) { console.log(nodes) });
}]);
I've also tested with a local deployd-Server. Same problems there.
How can i resolve this?
Thanks in advance for your help.
Is there a plunker example showing how to use Restangular? One working example is worth 10 pages of documentation!! :)
Hi Martin!
I try to set a Slash to the end of the URLs with setRequestSuffix but after that the URL ends with an escaped "%2F".
The Restful Framework Tastypie for Django needs a slash by default. You can change this in Tastypie and Django, but djangos url dispatcher works only with an ending slash optimally.
My API returns object lists with a results
array, and some metadata about pagination. I'm trying to access the pagination data in the view, but it doesn't seem to be attached to the $scope
. I also attached the response to window
, and in the console, I can see:
response.meta
Object {count: 2, next: null, previous: null}
However, in my view, $scope.things.meta
is undefined. Am I doing this wrong?
My Restangular config:
.config(function (RestangularProvider) {
// List views return JSON object, with `results` and page parameters.
RestangularProvider.setListTypeIsArray(false);
// Extract the actual list
RestangularProvider.setResponseExtractor(function (response, operation) {
// This is a get for a list
if (operation === 'getList') {
// Return an Array with one special property with all of the metadata
var newResponse = response.results;
newResponse.meta = {
count: response.count,
next: response.next,
previous: response.previous
};
console.log(newResponse);
window.response = newResponse;
return newResponse;
} else {
// An element
return response;
}
});
});
My controller:
angular.module('myapp')
.controller('MyCtrl', function ($scope, Restangular) {
var api = Restangular.all('app/api/v1/things');
$scope.things = api.getList();
My view:
<p>{{things.meta.count}}</p>
<p ng-repeat="thing in things">{{thing.name}}</p>
When doing a PUT using an existing object, there are fields being sent in the request payload that were not part of the object that was originally fetched.
e.g. some keys that shouldn't be there when being sent: parentResource, restangularCollection, and route.
Do you think it makes sense to strip these keys from the object before making the PUT call?
Add the ability to send queryParams in Post as it's possible now in get, put, delete
Add support for response interceptors. For example, i have a web service which wraps all responses in an envelope containing metadata like
{
meta : {
status : '0k'
}
data : {
name :'alice'
id '1000'
}
}
in this case, what i'm after is response.data.
In addition it would be useful to allow for request interceptors as well (so we can convert data into a form more suitable to the backend service).
For now, you can't do something like:
Restangular.all("accounts").getList().then(function(accounts) {
accounts.post({... data ...});
});
because POST expect to have a first attributes as a String indicating which sub-url the POST should be called, meaning there is no way to do POST on a "top" level url (or I didn't find how...).
The previous use case seems quite important to me since it's the standard way to add a new element to a collection.
Can you please put some simple CRUD example in Plunker?
Change instance variables for configuration to local var to reduce visiblity
The documentation says that baseUrl defaults to empty string, which actually defaults to the current Angular´s app url. This can be confusing especially when is necessary to set a different domain for the API´s url. The documentation could give another example for these cases, like:
app.config(function(RestangularProvider) {
RestangularProvider.setBaseUrl('http://myhost/api/v1');
});
Details here (saw your comment about restangular there): http://www.bennadel.com/blog/2433-Using-RESTful-Controllers-In-An-AngularJS-Resource.htm
/messages/clear-all
/messages/4/archive
Basically to perform actions outside REST methods.
Add the ability to send custom headers in every method for Angular > 1.1.3. Check:
Lodash seems faster, updates sooner and has more features.
Add a hook function afterRestangularize
to be called after an element has been restangularized (added Restangular's methods)
Add a new way to add new custom methods so that we can easily use them.
For example:
RestangularProvider.setAfterRestangularize(function(elem, isCollection, route) {
// Only enhance Building elements
if (!isCollection && route === "buildings") {
// addRestangularMethod signature is: methodName, operation, path, params, headers, elemToPost. All but methodName and operation are optional.
elem.addRestangularMethod("evaluate", "get", "evaluate", {single: true});
}
});
// Later in the code
// GET /buildings/123/evaluate?single=true
Restangular.one("buildings", 123).evaluate();
Does anybody have an idea on how to do this different? Or something that you think is better?
Some REST API require some headers to be sent on all requests like authentication.
It would be great if we could add them to configuration instead of passing them as a parameter in every request.
More of a question vs issue. In reviewing the code, you are using $resource for the calls. With $http, you can cache the query. Have you thought about query caching? or are you going to leave that outside of the scope of Restangular? Rob.
$resource adds a bunch of methods to Restangular. This makes it impossible to use a $watch for Object equality.
I'm not really sure what the problem is. I've tried with Angular 1.0.6 and with 1.1.4 (error below when using 1.1.4) and I keep getting this same error.
Relevant JavaScript:
app.config(function(RestangularProvider) {
var r = RestangularProvider;
r.setBaseUrl('/api/contacts')
r.setResponseExtractor(function (response, operation, what, url) {
if (operation === 'getList') {
var newResponse = response.objects;
newResponse.metadata = response.meta;
return newResponse;
} else {
return response;
}
});
});
app.controller('groupsController', function ($scope, Restangular) {
$scope.groups = [];
$scope.getGroups = function () {
Restangular.all('groups').getList().then(function (groups) {
$scope.groups = groups;
});
}
$scope.getGroups();
});
TypeError: Object #<Resource> has no method 'push'
at copy (http://example.com/static/js/angular.js:600:21)
at new Resource (http://example.com/static/js/angular-resource.js:392:9)
at angular.module.factory.Resource.(anonymous function).value.$then.promise.then.value.$then (http://example.com/static/js/angular-resource.js:465:30)
at forEach (http://example.com/static/js/angular.js:158:20)
at angular.module.factory.Resource.(anonymous function).value.$then (http://example.com/static/js/angular-resource.js:464:17)
at deferred.promise.then.wrappedCallback (http://example.com/static/js/angular.js:7303:59)
at deferred.promise.then.wrappedCallback (http://example.com/static/js/angular.js:7303:59)
at ref.then (http://example.com/static/js/angular.js:7340:26)
at Object.$get.Scope.$eval (http://example.com/static/js/angular.js:8685:28)
at Object.$get.Scope.$digest (http://example.com/static/js/angular.js:8548:23) angular.js:6173
$get angular.js:6173
$get angular.js:5219
deferred.promise.then.wrappedCallback angular.js:7305
deferred.promise.then.wrappedCallback angular.js:7303
ref.then angular.js:7340
$get.Scope.$eval angular.js:8685
$get.Scope.$digest angular.js:8548
ng.config.$provide.decorator.$delegate.__proto__.$digest example.com:820
$get.Scope.$apply angular.js:8771
ng.config.$provide.decorator.$delegate.__proto__.$apply example.com:831
done angular.js:10004
completeRequest angular.js:10180
xhr.onreadystatechange
Having following service:
angular.module('app.services', []).
factory('TestService', ['Restangular', function (restangular) {
var testResource = restangular.all('tests');
return {
getTests: function () {
return testsResource.getList({}, {'name': 'value'});
},
getTest: function (testID) {
return restangular.one('tests', testID).get({}, {'name': 'value'});
}
};
}]);
If calling getTests or getTest I assume the header is set but it isn't. Am I doing something wrong?
I have Restangular configured with the following code:
angular.module('MyApp', ['restangular'])
.config(function (RestangularProvider) {
RestangularProvider.setRequestSuffix('\\/');
});
This causes Restangular to request resources with two "/" characters at the end, like /api/myresource//
, which doesn't work. Without it, the request is made to /api/myresource
, which also doesn't work. The only proper URL on my API is /api/myresource/
. Without the trailing slash it responds with a 301 redirect which is fine for GET but other methods don't work.
In case you want to create a "tree" of objects without actually navigating them, let's add a way of calling one
in collections (for some child element) and all
in elements (for some child collection)
Hi all,
I was wondering how I could "update" a restangular collection after modifying an item.
I can successfully send a PUT request to mt server to update the item but I don't now how to update my collection in my $scope.
Thanks in advance for any help,
Julien
Now it is possible to handle custom response formats by using the setResponseExtractor callback however that only works if the format is exactly the same. Now what if getting users returned this:
{
"status":"success",
"data": {
"users": [{
//data
}]
}
}
but getting posts is formatted like this:
{
"status":"success",
"data": {
"posts": [{
//data
}]
}
}
If we had access to a piece fo information that could help us handle this type of situtation, like the url or the name of the resource, in the setResponseExtractor callback, I think that would be a great addition to this library.
A lot of WebServers require sufixes with formats to be sent to figure out the Content Type of the answer. In some of them it's optional but not required as if that's absent, the ContentType of the request is used.
So the idea is to add a Sufix value to be configured in Restangular so that if you need all your requests to end in ".json", you can do that.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.