Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/dbankier/nano

A simple two-way data-binding library for Appcelerator's Alloy framework for Titanium.
https://github.com/dbankier/nano

Last synced: about 2 months ago
JSON representation

A simple two-way data-binding library for Appcelerator's Alloy framework for Titanium.

Awesome Lists containing this project

README

        

# Nano Titanium

A simple two-way data-binding library for Appcelerator's Alloy framework for Titanium.

## Install

From the root of your existing alloy project you can either.

Install using [gitto](http://gitt.io/)

~~~
$ gittio install nano
~~~

or install using npm

~~~
$ npm install ti-nano
~~~

It will copy all the required libraries to your `app/lib` folder.

## Setup

Add the following to the beginning of your controller:

~~~
var nano = require("nano");
nano.syntax(/\-\=(.+?)\=\-/gi);
~~~

For an explanation of the `syntax` command see the binding section.

Create an object you want to bind against, e.g.

~~~
var $model = {
person: {
first: "David",
last: "Bankier"
},
field:"asdf"
};
~~~

Then add the following to the end of your controller.

~~~
nano($,$model);
~~~

The object can really be any POJO, e.g. you can use args

~~~
var args = arguments[0];
nano($,args);
~~~

N.B. using `this` is not really recommended.

## Binding

Binding is two-way by default. So any changes in the view is reflected in the model and vice-versa.

The default syntax is `{{ attribute }}`. Currently there is a limitation in Alloy that prevents its usage.
See [this issue](https://github.com/dbankier/nano/issues/1).
The default syntax can be changed using the `nano.syntax` command.

For the examples below the follow command was used to change the syntax:

~~~
nano.syntax(/\-\=(.+?)\=\-/gi);
~~~

This changes the syntax `-= attribute =-`.

### Simple Cases

That aside you can bind against view properties like this:

~~~




-=person.first=-

~~~

You can also bind multiple values as follows.

~~~





Hello, -=person.first=- -=person.last=-

~~~

### expression

Binding also be against expression.

~~~





Hello, -=person.first=- -=person.last=-, length: -=person.last.length=-


Length: -=field.length=-

~~~

You can bind with any js expression that can be evaluated and against any
view property. Here is a validation example.

~~~








~~~

### One-Way binding

You can use the `oneway` attribute if you want force one-way binding.
This is part of the building `nano-oneway` plug-in.

~~~







~~~

### Changes in the controller.

Until we have `Object.observe` support, if you make changes in the controller to the `$model` then you
need to call the following command to trigger the updates to all bound views.

~~~
nano.apply();
~~~

## Plugins

### Loading

Load your plug-ins once, in your `alloy.js` file. For example:

~~~
var nano = require("nano");
var debounce = require("nano-debounce");
nano.load(debounce());
~~~

#### Official Plugins (see #7)

* [nano-debounce](https://github.com/dbankier/nano-debounce) - add a debounce delay so that changes in the view are only applied to the model after a timer expiry of inactivity
* [nano-class](https://github.com/dbankier/nano-class) - bind the model to the class (style) of a view.
* [nano-bindon](https://github.com/dbankier/nano-bindon) - change the view bind event from `change` to any other.

### Wrting

See the `src/plugins` folder for some examples in order to create a plug-in.

You can hook into the following events:

* `model:bind` - called prior to binding to a model property.
* `model:change` - called when a model change is detected.
* `view:init` - called prior to initialising the view with the bound model values.
* `view:bind` - called prior to adding a listener to the `change` event of the bound view.
* `view:change` - called when the `change` event of the view is called.

A hook is added in your plug by calling the `hook` command. For example, the one-way binding plug-in:

~~~
// Initialises and properties in template/expression that aren't in the $model
module.exports = function(options) {
return function(nano) {
nano.hook('model:bind', function(args, next) {
if(!args.view.oneway) {
next();
}
});
};
};
~~~

The following arguments are passed when the hook is called:

* `args` - this object contains the following properties:
- `$` - `$` from the controller
- `$model` - the bound model
- `view` - bound view raising the event, e.g. the `Ti.UI.Label`
- `prop` - the view's bound property raising the event, e.g. `text` (for `model:bind` this is the property of the model)
- `expr` - the bound expresion, e.g. if the value of text is `Surname length: {{last.length}}`, `expr` would be `last.length`
* `next` - the hooks act like middle and are executed in the order they were loaded. `next` is a callback to continue.

## Building from Source

Building the distributable is done using [grunt](http://gruntjs.com/)

Enter the following:

~~~
$ npm install
$ grunt
~~~

The built library is found in at `dist/nano.js`

## Under The Hood

It uses Polymer's [object-js](https://github.com/polymer/observe-js) to fill in the gaps
until we get `Object.observe` in Titanium.

## Why

This was originally motivated by seeing [this](http://beautyindesign.com/blog/uber-simple-idea-for-alloy-view-data-binding/) by @rblalock.

I rarely use backbone models built-in to Alloy. Also having been spoilt by the data-binding
options for web-developers I find the data-binding built into Alloy limited and overly complicated.