interbind v0.1.0
interbind
A binding and event library useful for implementing the MVC pattern for JavaScript/TypeScript.
WARNING: This library is in early stages of development. Breaking API changes are expected to happen. See the GitHub issues for more information.
Binding
Binding is the process of establishing a connection between two properties. They are an event-based data flow abstraction managed by the BindingService
class and its exposed decorators.
NOTE: The behaviour and function of bindings are similar to data binding in WPF.
Bindings are made up of two components:
- A
bindable
, which is the source property in the binding relation. It can have multiple properties targeting it as their source. - A
bound
which is a replica of the bindable property it targets.
Additionally, each binding has a number of optional arguments to configure its behaviour. These include:
- the mode with which to bind properties.
- One-way binding causes changes to the
bindable
property to automatically update thebound
property, but changes targeting thebound
property are not propegated back to thebindable
property. - Two-way binding causes changes to either the
bindable
property or thebound
property to automatically update the other.
- One-way binding causes changes to the
- the action which allows the class of the
bound
property to respond to changes (e.g. refresing a view). - the transform to use on the
bindable
data when updating thebound
property. (Only available on one-way bindings.)
Usage
Import the binding components of the library you would like to use.
import { /* BindingService, Bindable, Bind, etc. */ } from "interbind";
bindable
A bindable
can be created in the following ways:
- declaratively using a TypeScript decorator:
class Source {
@Bindable
public text?: string;
}
- imperatively using the
BindingService
class: NOTE: The imperative definition of binding components is subject to change in the very near future.
class Source {
public text?: string;
constructor() {
BindingService.markBindable(this, "text", String);
BindingService.makeBindable(this, "text");
}
}
bound
A bound
can be created similarly, using either a declarative or imperative syntax. For example, a binding to an instance of the previously defined bindable would look like this:
- delaratively using the TypeScript decorator:
NOTE: The use of the
BindingService.init()
call is mandatory to initialize allbound
properties declared using decorators. (Static properties reside on their class and thus have to be initialised seperately from instanced properties.)
let src: Source = new Source();
class Replica {
@Bind(src, "text")
public text?: string;
constructor() {
BindingService.init(this);
}
}
- imperatively using the
BindingService
class:
let src: Source = new Source();
class Replica {
public text?: string;
constructor() {
BindingService.bind(this, "text", src, "text");
}
}
Example
Here is an example for use with a React component (and corresponding backing store):
import { BindingService, Bindable, Bind, ReactBind } from "interbind";
BindingService.defaultBindAction = ReactBind;
public class User {
public username: string;
}
public abstract class UserManager {
@Bindable
public static currentUser: User;
}
public class Navigation extends React.Component<any, any> {
@Bind(UserManager, "currentUser")
private user: User;
componentDidMount() {
BindingService.init(this);
}
render() {
return (
<div>{this.user ? this.user.username : "login"}</div>
)
}
}
6 years ago