Skip to content

Repository files navigation

ng-hyper

hyper+json client tools for angular.js

Installation

Component:

$ component install hypergroup/ng-hyper

Usage

Add ng-hyper as a dependency of your angular app.

angular.module('my-app',['ng-hyper']);

Building ng-hyper (optional)

$ npm install
$ make build

Running tests

By default, tests are run against AngularJS 1.0.8.

$ make tests

To switch AngularJS version, override the NG_VERSION variable with a different value, e.g.

$ make tests NG_VERSION=1.1.0

Components

Directives

hyper

hyper binds the value at the path to the scope. The name of the bound value defaults to the last property in the path.

<divdata-hyper=".users"><!-- 'users' is now available in this scope --></div>

If a name other than the last property in the path is needed use as.

<divdata-hyper=".users as usersList"><!-- 'usersList' is now available in this scope --></div>

hyper should always be used when passing data into an angular directive.

<divdata-hyper=".account"><!-- BAD!!! names.first may be in the reponse right now but the server may change it in the future! --><spandata-ng-bind="account.names.first"></span><!-- GOOD!!! by using the data provided by 'hyper' the client will be future proof --><spandata-hyper="account.names.first" data-ng-bind="first"></span></div>

hyper directives may be nested as needed.

<uldata-hyper=".users"><lidata-ng-repeat="user in users"><spandata-hyper="user.name" data-ng-bind="name"></span><span>likes</span><ulclass="likes" data-hyper="user.likes"><lidata-ng-repeat="like in likes"><spandata-hyper="like.name" data-ng-bind="name"></span></li></ul></li></ul>

Multiple values may be bound on a single element with a comma separated list.

<divdata-hyper=".users, .posts, .status as currentStatus"><!-- 'users', 'posts' and 'currentStatus' are now available in this scope --></div>

Because it becomes very verbose to use hyper before passing data to non-hyper directives ng-hyper provides some additional directives.

hyper-bind

Instead of using a combination of hyper and ng-bind use hyper-bind instead.

<divdata-hyper=".account"><!-- more verbose --><spandata-hyper="account.name" data-ng-bind="name"></span><!-- less verbose --><spandata-hyper-bind="account.name"></span></div>

hyper-link

TODO

<uldata-hyper=".users"><lidata-ng-repeat="user in users"><adata-hyper-link="/users/:user" data-hyper-bind="user.name"></a></li></ul>

hyper-form

TODO

<divdata-hyper=".account"><formdata-hyper-form="account"><!-- 'inputs' is now available in the scope --></form></div>

hyper-input

TODO

<divdata-hyper=".account"><formdata-hyper-form="account"><divdata-ng-repeat="input in inputs"><inputdata-hyper-input="input" /></div></form></div>

hyper-img

Instead of using a combination of hyper and ng-src use hyper-img instead.

<divdata-hyper=".account"><!-- more verbose --><imgdata-hyper="account.image.src" data-ng-src="{{src}}"></img><!-- less verbose --><imgdata-hyper-img="account.image"></img></div>

hyper-redirect

TODO

<divdata-hyper-redirect="/users/:.account"></div>

Services

hyper

hyperPath

hyperLink

hyperLinkFormatter

hyperBackend

hyperHttpEmitter

hyperStatus

Controllers

hyper

Concepts

Hypermedia

ng-hyper uses the hypermedia type hyper+json. It is recommended reading the spec before using ng-hyper.

This toolset can most accurately be thought of as a 'hypermedia transformer' that takes one hypermedia format (hyper+json) and converts into another (HTML), similar to XSLT (only much simpler).

Path traversal

ng-hyper makes it easy to consume hyper+json apis by wrapping traversal of links and properties in a consistent syntax. The path syntax is represented by the 'dot notation'.

Consider the following set of resources:

{
"href": "/",
"status": "ok",
"users": {
"href": "/users"
}
}
{
"href": "/users",
"collection": [
{"href": "/users/1"},
{"href": "/users/2"},
{"href": "/users/3"}
]
}
{
"href": "/users/1",
"name": "Cameron"
}
{
"href": "/users/2",
"name": "Mike"
}
{
"href": "/users/3",
"name": "Tim"
}

Values are easily accessed as properties and links are traversed:

.status
// 'ok'
.users
// [{href: ...}, ...]
.users.0.name
// 'Cameron'
.users.1.name
// 'Mike'

Paths starting with . signify starting at the root document. If a path uses a resource as its context, paths without .s refers to the given context.

Consider the following resources:

{
"href": "/users/1",
"name": "Cameron",
"friends": [
{"href": "/users/2"},
{"href": "/users/3"}
]
}
{
"href": "/users/2",
"name": "Mike"
}
{
"href": "/users/3",
"name": "Tim"
}

Using /users/1 as the context resource the following paths will yield the proceeding results:

name
// 'Cameron'
friends
// [{href: ...}, ...]
friends.0.name
// Mike
friends.1.name
// Tim

Because the syntax is unaware of links it makes it easy to embed/extract resources from parent resources.

Consider the following resource:

{
"href": "/",
"likes": [
{"name": "hot-dogs"},
{"name": "toasters"},
{"name": "spoons"}
]
}

At the moment this resource is a standalone resource. The list of likes can be accessed with:

likes
// [{'name': 'hot-dogs'}, ...]
likes.0.name
// 'hot-dogs'
likes.1.name
// 'toasters'

Suppose the server has decided to split out the likes into their own resources, to make is easier to count the number of total likes of a particular item. This would result in the following resources:

{
"href": "/",
"likes": [
{"href": "/likes/hot-dogs"},
{"href": "/likes/toasters"},
{"href": "/likes/spoons"}
]
}
{
"href": "/likes/hot-dogs",
"count": 3
}
{
"href": "/likes/toasters",
"count": 9
}
{
"href": "/likes/spoons",
"count": 4
}

The previously used paths continue to work because ng-hyper transparently follows links until it finds the property.

likes
// [{'name': 'hot-dogs'}, ...]
likes.0.name
// 'hot-dogs'
likes.0.count
// 3
likes.1.name
// 'toasters'

Now suppose the server decided, for caching reasons, it would be better to split the collection of likes from the root resource into its own:

{
"href": "/",
"likes": {
"href": "/likes"
}
}
{
"href": "/likes",
"collection": [
{"href": "/likes/hot-dogs"},
{"href": "/likes/toasters"},
{"href": "/likes/spoons"}
]
}
{
"href": "/likes/hot-dogs",
"count": 3
}
{
"href": "/likes/toasters",
"count": 9
}
{
"href": "/likes/spoons",
"count": 4
}

As before, the client will continue to work.

About

hyper+json client tools for angular.js

Resources

Stars

6 stars

Watchers

4 watching

Forks

Releases

Packages

Contributors

Languages