README.md
[![Travis Status for radify/angular-model](https://travis-ci.org/radify/angular-model.svg)](https://travis-ci.org/radify/angular-model)
[![Coverage Status](https://coveralls.io/repos/radify/angular-model/badge.svg?branch=master&service=github)](https://coveralls.io/github/radify/angular-model?branch=master)
[![Dependency Status](https://david-dm.org/radify/angular-model.svg)](https://david-dm.org/radify/angular-model)
[![devDependency Status](https://david-dm.org/radify/angular-model/dev-status.svg)](https://david-dm.org/radify/angular-model#info=devDependencies)
[![Code Climate](https://codeclimate.com/github/radify/angular-model/badges/gpa.svg)](https://codeclimate.com/github/radify/angular-model)
# Angular Model
## Simple HATEOS-oriented persistence module for AngularJS.
**Angular Model** is a module that provides a simple way to bind client-side domain logic to JSON-based API resources.
By sticking to hypermedia design principles, Angular Model allows you to implement client applications that are cleanly decoupled from your server architecture.
## Basic Usage
In your AngularJS application, include the JavaScript:
```html
// your specific paths may vary
<script src="node_modules/radify/angular-model.js"></script>
```
In your app configuration, state a dependency on [Angular Model](https://github.com/radify/angular-model):
```javascript
angular.module('myApp', [
'ur.model'
]);
```
## API documentation
The source code is documented using the ngdoc standard using [gulp-ngdocs](https://www.npmjs.com/package/gulp-ngdocs/). A markdown version is browseable at [/docs](/docs/api.md).
To generate documentation in HTML, run:
```bash
gulp ngdocs
```
This will output docs into the `build/docs` directory. Then, using a server like `ws`, start a local web server:
```bash
cd build/docs
npm install -g ws
ws
```
Then, you should be able to browse to http://localhost:8000 to view the API documentation for angular-model.
## Configuration
Here is a quick reference guide to all the configuration settings you can pass to the model() constructor, which is [documented in full in the API documentation](/docs/api.md). Each one is then described in detail later in this document, and in full in the source code in the `src` directory.
Setting | Type | Description
------- | ---- | -----------
url | string | API url that this model maps to
defaults | object literal | Default values of attributes of instances of this model. Similar to properties in OOP.
$instance | object literal | Instance methods available on each instance of this model.
$class | object literal | Class methods available on this model. Similar to static methods in OOP.
$collection | object literal | Collection
### Defaults
```javascript
yourApp.config(function(modelProvider) {
modelProvider.model('posts', {
/**
* @ngdoc object
* @name yourApp.posts.defaults
* @description
* Configure the default attributes for instances of posts.
*
* This is similar to an OOP class, which has attributes with defaults, e.g. "public string foo = 'bar';"
*/
defaults: {
name: '', // The name of the post
published: false, // Whether the post has been released to the general public
body: '', // Body text of this post
logo: null, // The logo to show for this post
author: 'John Doe'// Who wrote the post?
}
});
});
```
Here is an example of how the defaults get used:
```javascript
var post = model('posts').create({});
console.log(post.author);
=> John Doe
```
## Creating instances of your model
You can use angular-model ad-hoc to construct object instances:
```javascript
// From defaults
var post = model('posts').create({});
// Specifying fields
var post = model('posts').create({
name: 'some post',
body: "body of some body, it's just some body, you know?",
author: 'Steve Davis'
});
console.log(post.author);
=> Steve Davis
```
## Instance Methods
angular-model instances have instance methods, similar to objects in the OOP world.
### Default instance methods
The following methods are available to every angular-model instance.
Function | Description
------- | -----------
$save | Persist an instance to the API
$delete | Tell the API to delete an instance
$reload | Refresh an instance of a model from the API
$revert | Reset the model to the state it was originally in when you first got it from the API
$exists | Checks whether an object exists in the API, based on whether it has an identity URL.
$dirty | Returns boolean - true if a model instance has been modified, else false. Opposite of $pristine.
$pristine | Returns boolean - true if a model instance has unmodified, else false. Opposite of $dirty.
$related | Hydrates the $links property of the instance. $links are used so that an instance can tell the client which objects are related to it. For example, a `post` may have an `author` object related to it.
$modified | Returns a map of the properties that have been changed
$hasRelated | Does an instance have a relation of name `name`?
> You can see full details of these methods in the [API documentation](/docs/api.md).
### Custom instance methods
angular-model allows you to define instance methods on instances. This is similar to adding methods by extending a base class in the OOP world.
```javascript
yourApp.config(function(modelProvider) {
modelProvider.model('posts', {
// ...
/**
* @ngdoc object
* @name yourApp.posts.$instance
* @description
* Instance methods that are callable on any individual instance of a post
*/
$instance: {
/**
* @ngdoc function
* @name yourApp.posts.$logo
* @description
* If this post instance has a logo, return it, otherwise return a default string
*
* @return string Either the logo for this post, or a default logo
*/
$logo: function() {
return this.logo || '/logos/default.png';.
}
}
});
});
```
Example:
```javascript
var post = model('Posts').create({
logo: 'foo.png'
});
console.log(post.$logo());
=> foo.png
```
## Class methods
### Default class methods
The following methods are available statically to angular-model:
Function | Description
-------- | -----------
all | Make a request to the API, based on the `url` configuration setting
first | Given a query, get the first model instance from the API
create | Create a new instance of the model. Defaults come from the `defaults` configuration setting.
> You can see full details of these methods in the [API documentation](/docs/api.md).
### Custom class methods
angular-model allows you to define class methods on instances. This is similar to static methods in the OOP world.
```javascript
yourApp.config(function(modelProvider) {
modelProvider.model('posts', {
// ...
/**
* @ngdoc object
* @name yourApp.posts.$class
* @description
* Class methods that are callable on the posts class, or any instance thereof. These
* behave similarly to static methods in OOP languages.
*/
$class: {
/**
* @ngdoc function
* @name yourApp.posts.roles
* @description
* Get an array of valid post types.
*
* @return array The valid types that a post can have. Array of strings
*/
types: function() {
return ['announcement', 'article']
}
}
});
});
```
Example:
```javascript
console.log(model('Posts').types());
=> ['announcement', 'article']
```
## Collection methods
You can use collection methods as well, so you can deal with a bunch of instances together. This allows you to have powerful and expressive methods on collections.
### Default collection methods
The following methods are available statically to angular-model:
Function | Description
-------- | -----------
add | Saves the `object` with `data`
remove | Find `index` and delete it from the API, then remove it from the collection
> You can see full details of these methods in the [API documentation](/docs/api.md).
### Custom collection methods
```javascript
yourApp.config(function(modelProvider) {
modelProvider.model('posts', {
// ...
/**
* @ngdoc object
* @name yourApp.posts.$collection
* @description
* Methods that apply to a collection of posts together
*/
$collection: {
/**
* @ngdoc function
* @name yourApp.posts.$hasArchived
* @description
* Operates on a collection of posts and determines whether any of them are archived
*
* @requires _ Lodash library is used to search the collection
*
* @return string Either the logo for this post, or a default logo
*/
$hasArchived: function() {
return !angular.isUndefined(_.find(this, { archived: true }));
}
}
});
});
```
Example:
```javascript
model('Posts').all().then(function(posts) {
if (posts.$hasArchived()) {
// Some of the posts in the collection are archived
}
});
```
Running unit tests
--
Install the test runner with npm:
```bash
npm install
```
You can then run the tests with gulp:
```bash
gulp
```
Tests can be found in the `spec` directory of this project.
Related
--
You may wish to use [Angular Scaffold](https://github.com/radify/angular-scaffold/), which is is a collection of convenience wrappers around angular-model collections. Really helpful for building your AngularJS application with angular-model.