Collection Resource
Collection Resource is a simple but powerful AJAX resource library for Angular. It makes requests assuming REST API, and works with plain old JavaScript objects.
Installation
Install with NPM
npm install collection-resource
Usage
To use with angular add it as a module:
var app = angular;
Create your model using:
app;
Now you can use your Users model in your controller, like:
app;
Basic methods
A collection resource has a few basic methods with which you can fetch data from server. You can also extend collection resource with your additional methods. Below you can see methods usage assuming Users collection and /api/v1/users api as example. Most methods return a promise.
.query([params]) / .where([params])
Requests a list and returns a promise.
var promise = Users;
.get(id[, params]) / .find(id[, params])
Requests a single resource by id
var promise = Users;
Creating and updating an object
For the most part, Collection Resource works with any Object, for example:
var user = id: 10 name: 'Nick'; var promise = Users;
This will send a PATCH request to /users/10 api path with user data.
By default Collection Resource will try to recognize, by existance of id (or primary field) which request to send POST or PATCH.
For other cases where you want to force a POST/CREATING request you can use .make() to mark those objects as new for POST-ing.
.make([newObject])
var newUser = Users; var promise = Users;
This will send a POST request to /users api path with user data. .make() only marks your objects with special properties with which Resource can recognize which request to send.
.from(objectOrArray)
You can use .from to convert a new (marked with .make()) object into a simple existing object.
var user = Users;// Sends a POST request to /usersUsers; userid = 10;user = User;// Sends a PATCH request to /users/10Users;
You can use this to run property casting or hydrator (described below) on models which you made in memory or saved to local storage.
.save(object[, params])
var promise = Users;
.saveProp(objectOrArray, key[, params])
Saves object property and redirects response to the same property (see .to() helper).
// Sends the property to server and sets the response to the propertyvar promise = Users; // orvar promise = Users; // orUsers
Special promises
Returned promises have a few special methods, other then .then( ) and .catch, which can make your code simpler.
.to(objectOrArray[, objectProperty])
.to() can extract data from response to a variable or object. It can recognize when response has a data property and it extracts only the data property, or fallbacks to full response.
Users; // or $scopeusers = ;Users;
But you can always attach .then:
Users ;
Combine with .save()
var user = Users;Users; // or Users;
.fetching(object, property)
Sets object property to true while request is running, and sets to false when request is finished. This can be useful for adding loading spinners.
Users ; // Use in template<div ng-if="loading" class="loading-spinner">...</div><div ng-if=" ! loading" class="users-list">...</div> // orUsers;// In template<button ng-disabled="saving" ng-... > Save </button>
.thenData(callback)
When response has data property it gives you data property, otherwise it gives you full response
/*Server response:[ {"name": "Nick"}] Or: { "data": [ {"name": "Nick"} ]} Both responses will give you the list*/Users ;
.error(callback) and .catch(callback)
By default you will get a warning for every request that you haven't added .catch() or .error() handler. The difference with .error() is that the original promise is passed through.
Users ; // Executes on successful response, doesn't chain to .error // or Users // handle recovery ;
.abort()
Aborts a request:
var request = Users; if shouldAbortCondition request;
.bind($scope)
Binds request to $scope lifecycle and aborts request when $scope is destroyed.
Users ;
Identity Map
Collection resource has identity map implementation. It can track your models by id (or primary field) and keep a single memory reference to your objects, so you can load models from server without keeping track of multiple references and changes yourself.
This gives you the same object by id (or primary field) every time. So you can never get double objects and model synchronization problems.
You can use several requests to load the same data, and the references will be the same, and when you edit one, the other will also be changed.
// This will fetch a user by id of 10Users; // This will also fetch a user with id 10. But the user with id 10// will override already fetched user by id 10// So this will refresh $scope.selected from the sample aboveUsers;
Since this keeps models by id in memory we can also skip requests to server, and we get automatic caching.
// Here we fetch some usersUsers; // When the first request is loaded, we know we already have user by id 10// so you get a local reference and the request to server is never madeUsers;
This can make your app much faster, since you can preload models partialy or fully in advance. You can enable this with:
app;
Fetch local and refresh from server
Sometimes you might want to do both: get the local (already loaded) reference and also refresh it with server request. You can do this by adding reload: true to .get(id) request parameters:
// Assume we have id 10 already loaded with// Users.query().to($scope.users) // This request will give you id 10 immediately but will also go to server// and reload with fresh changesUsers;
Partial models
You can also partialy load models, here's an example how you can implement partial loading of "list" and "detail" requests (assuming you implement backend API similarly):
// This is a request for the list interfaceUsers // User clicks more to see more details for model by id 10Users
Extensions
Extend Model
You can extend your Collection Resource with helper methods during definition, for example:
app; // Use withUsers;// orUsers;
Extend single item
You can add methods to single items if you need it, but the recommended way is to leave your JavaScript objects as is. Here's an example:
app; // Usage Users;...$scopeuser;$scopeuser;
Extend Collection Resource
If you want to develop advanced addon's for Collection Resource, you can use Resource.extend() to do that, and you can see the official addon for Undo/Redo functionality for example. Here's how to extend Collection Resource:
angular ; // UsageUsers;Users;
Property casting
You can preprocess or cast item properties during fetching and hydration phase. This can be usefull for dates, JSON properties, comma separated values or other.
There is already built in cast for date type, but you can also pass a function to create your own. Here's an example:
app; // Fetch and useUsers...console // Converted to Dateconsole // Converted to booleanconsole // Converted to Arrayconsole // Converted from JSON to object