react-binding
React-binding is lightweight utility for two-way data binding in React.
Note: React-binding as mixins - use npm install react-binding@0.6.4
import {Binder} from 'react-binding'
Binder.bindToState(this,"data","__Employee.FirstName__");
Binder.bindToArrayState(this,"data","__Hobbies__");
Binder.bindTo(__employee__,"__Contact.Email__");
Binder.bindToArray(__employee__,"__Hobbies__");
Binder.bindToState(this,"data","__Employee.FirstName__");
Binder.bindToArrayState(this,"data","__Hobbies__");
Binder.bindTo(__employee__,"__Contact.Email__");
Binder.bindToArray(__employee__,"__Hobbies__");
BindToMixin offers two-way data binding support for:
- object properties with path expression (dot notation)
- Binder.bindToState(this,"data","Employee.FirstName");
- Binder.bindToState(this,"data","Employee.Contact.Email");
- complex objects (json) with nested properties
- Binder.bindTo(employee,"FirstName");
- Binder.bindTo(employee,"Contact.Email");
- collection-based structures - arrays and lists
- model={Binder.bindArrayToState(this,"data","Hobbies")}
- this.props.model.items.map(function(item){ return ();})
- this.props.model.add()
- this.props.model.remove(item)
- supports for "value/requestChange" interface also to enable to use ReactLink attribute
- valueLink={Binder.bindTo(employee,"FirstName")}
- enables binding with value converters
- supports both directions - format (toView) and parse (fromView)
- support for converter parameter - valueLink={Binder.bindToState(this,"data", "Duration.From",converter, "DD.MM.YYYY")}
- converter parameter can be data-bound - valueLink={Binder.bindToState(this,"data", "Duration.From",converter, this.state.format)}
- usable with any css frameworks
Basic principle
Each bindTo return and uses interface called "value/onChange".
Each bindTo component is passed a value (to render it to UI) as well as setter to a value that triggers a re-render (typically at the top location).
The re-render is done in the component where you bind to the state via (bindToState, bindArrayToState).
BindTo can be nested - composed to support components composition. Then path is concatenate according to parent-child relationship.
Get started
npm install react-binding
bower install react-binding
npm install -g browserify
npm install reactify
browserify ./index.js > bundle.js
minimal example
import React from 'react';
import {Binder} from 'react-binding'
var Form = React.createClass({
getInitialState: function () {
return {data: {}}
},
render: function () {
return (
<div>
<input valueLink={Binder.bindToState(this,"data", "FirstName")} />
<div>FirstName: {this.state.data.FirstName}</div>
</div>
)}
});
React.render(
<Form />,
document.getElementById('content')
);
Overview
bindToState(key,pathExpression)
It enables to bind to object property with path expression
<input type='text' valueLink={Binder.bindToState(this,"data","Employee.Contact.Email")} />
<TextBoxInput model={Binder.bindToState(this,"data","Employee.Contact.Email")} />
var TextBoxInput = React.createClass({
render: function() {
var valueModel = this.props.model;
var handleChange = function(e){
valueModel.value = e.target.value;
}
return (
<input type='text' onChange={handleChange} value={valueModel.value} />
)
}
});
bindTo(parent,pathExpression)
It enables to bind to complex object with nested properties and reuse bindings in components.
- binding to state at root level
<PersonComponent personModel={Binder.bindToState("data","Employee")} />
<PersonComponent personModel={Binder.bindToState("data","Deputy")} />
<input type='text' valueLink={Binder.bindTo(this.props.personModel,"Contact.Email")} />
- reuse bindings in component
var PersonComponent = React.createClass({
render: function() {
return (
<div>
<input type='text' valueLink={Binder.bindTo(this.props.personModel,"FirstName")} />
<input type='text' valueLink={Binder.bindTo(this.props.personModel,"LastName")} />
<input type='text' valueLink={Binder.bindTo(this.props.personModel,"Contact.Email")} />
</div>
);
}
});
bindArrayToState(key,pathExpression)
It enables binding to collection-based structures (array). It enables to add and remove items.
<HobbyList model={Binder.bindArrayToState(this,"data","Hobbies")} />
- access items (this.props.model.items)
var HobbyList = React.createClass({
render: function() {
if (this.props.model.items === undefined) return <span>There are no items.</span>;
var hobbies = this.props.model.items.map(function(hobby, index) {
return (
<Hobby model={hobby} key={index} onDelete={this.handleDelete} />
);
},this);
return (
<div>{hobbies}</div>
);
}
});
- add new items (this.props.model.add(newItem?))
handleAdd: function(){
return this.props.model.add();
},
- remove exiting items (this.props.model.props.delete(item))
handleDelete: function(hobby){
return this.props.model.remove(hobby);
},
bindArrayTo(parent,pathExpression)
It enables binding to collection-based structures (array) for nested arrays. It enables to add and remove items.
<HobbyList model={Binder.bindArrayTo(this,parent,"Hobbies")} />
- access items (this.props.model.items)
var HobbyList = React.createClass({
render: function() {
if (this.props.model.items === undefined) return <span>There are no items.</span>;
var hobbies = this.props.model.items.map(function(hobby, index) {
return (
<Hobby model={hobby} key={index} onDelete={this.handleDelete} />
);
},this);
return (
<div>{hobbies}</div>
);
}
});
- add new items (this.props.model.add(newItem?))
handleAdd: function(){
return this.props.model.add();
},
- remove exiting items (this.props.model.props.delete(item))
handleDelete: function(hobby){
return this.props.model.remove(hobby);
},
Value converters
Value converters
- format - translates data to a format suitable for the view
- parse - convert data from the view to a format expected by your data (typically when using two-way binding with input elements to data).
Example - date converter -> using parameters 'dateFormat' is optional
var dateConverter = function() {
this.parse = function (input, dateFormat) {
if (!!!input) return undefined;
if (input.length < 8) return undefined;
var date = moment(input, dateFormat);
if (date.isValid()) return date.toDate();
return undefined;
}
this.format = function (input,dateFormat) {
if (!!!input) return undefined;
return moment(input).format(dateFormat);
}
}
using converter
<DatePicker label="From" model={Binder.bindToState(this,"data", "Duration.From", converter, 'DD.MM.YYYY')} error={this.validationResult().Duration.From} />
<DatePicker label="To" model={Binder.bindToState(this,"data", "Duration.To", converter, 'DD.MM.YYYY')} error={this.validationResult().Duration.To} />
try in Plunker
Examples
hobby form - data binding only
hobby form with validation using business-rules-engine
value converters
Contact
For more information on react-binding please check out my blog.