Skip to content

Repository files navigation

react-binding

React-binding is lightweight utility for two-way data binding in React.

importReactfrom'react';importReactDOMfrom'react-dom';importBinderfrom'react-binding';exportdefaultclassFormextendsReact.Component{constructor(props){super(props);this.state={data: {}};},render{return(<div><inputvalueLink={Binder.bindToState(this,"data","Employee.FirstName")}/><div>FirstName: {this.state.data.Employee.FirstName}</div></div>)}});ReactDOM.render(<Form/>,document.getElementById('content'));

Features:

  • No dependencies.
  • Minimal interface - using path with dot notation.
  • Support for complex objects.
  • Support for collection-based structures - arrays and lists.
  • Support for value converters.
  • No need to define initial values, nested structures. Binder creates this for you.
  • Support concept for references to allow JSON to be used to represent graph information.

react-binding 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

npminstallreact-binding
bowerinstallreact-binding
npminstall-gbrowserifynpminstallreactifybrowserify./index.js>bundle.js

minimal example

importReactfrom'react';importReactDOMfrom'react-dom';importBinderfrom'react-binding';exportdefaultclassFormextendsReact.Component{constructor(props){super(props);this.state={data: {}};},render{return(<div><inputvalueLink={Binder.bindToState(this,"data","Employee.FirstName")}/><div>FirstName: {this.state.data.Employee.FirstName}</div></div>)}});ReactDOM.render(<Form/>,document.getElementById('content'));

Note: React-binding as mixins - use npm install react-binding@0.6.4

Overview

bindToState(key,pathExpression)

It enables to bind to object property with path expression

<inputtype='text'valueLink={Binder.bindToState(this,"data","Employee.Contact.Email")}/>
<TextBoxInputmodel={Binder.bindToState(this,"data","Employee.Contact.Email")}/>
varTextBoxInput=React.createClass({render: function(){varvalueModel=this.props.model;varhandleChange=function(e){valueModel.value=e.target.value;}return(<inputtype='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
<PersonComponentpersonModel={Binder.bindToState(this,"data","Employee")}/><PersonComponentpersonModel={Binder.bindToState(this,"data","Deputy")}/>
  • binding to parent
<inputtype='text'valueLink={Binder.bindTo(this.props.personModel,"Contact.Email")}/>
  • reuse bindings in component
varPersonComponent=React.createClass({render: function(){return(<div><inputtype='text'valueLink={Binder.bindTo(this.props.personModel,"FirstName")}/><inputtype='text'valueLink={Binder.bindTo(this.props.personModel,"LastName")}/><inputtype='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.

  • binding to array
<HobbyListmodel={Binder.bindArrayToState(this,"data","Hobbies")}/>
  • access items (this.props.model.items)
varHobbyList=React.createClass({render: function(){if(this.props.model.items===undefined)return<span>There are no items.</span>;varhobbies=this.props.model.items.map(function(hobby,index){return(<Hobbymodel={hobby}key={index}onDelete={this.handleDelete}/>);},this);return(<div>{hobbies}</div>);}});
  • add new items (this.props.model.add(newItem?))
handleAdd: function(){returnthis.props.model.add();},
  • remove exiting items (this.props.model.props.delete(item))
handleDelete: function(hobby){returnthis.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.

  • binding to array
<HobbyListmodel={Binder.bindArrayTo(this,parent,"Hobbies")}/>
  • access items (this.props.model.items)
varHobbyList=React.createClass({render: function(){if(this.props.model.items===undefined)return<span>There are no items.</span>;varhobbies=this.props.model.items.map(function(hobby,index){return(<Hobbymodel={hobby}key={index}onDelete={this.handleDelete}/>);},this);return(<div>{hobbies}</div>);}});
  • add new items (this.props.model.add(newItem?))
handleAdd: function(){returnthis.props.model.add();},
  • remove exiting items (this.props.model.props.delete(item))
handleDelete: function(hobby){returnthis.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

vardateConverter=function(){this.parse=function(input,dateFormat){if(!!!input)returnundefined;if(input.length<8)returnundefined;vardate=moment(input,dateFormat);if(date.isValid())returndate.toDate();returnundefined;}this.format=function(input,dateFormat){if(!!!input)returnundefined;returnmoment(input).format(dateFormat);}}

using converter

<DatePickerlabel="From"model={Binder.bindToState(this,"data","Duration.From",converter,'DD.MM.YYYY')}error={this.validationResult().Duration.From}/><DatePickerlabel="To"model={Binder.bindToState(this,"data","Duration.To",converter,'DD.MM.YYYY')}error={this.validationResult().Duration.To}/>

try in Plunker

References

JSON models trees, and most application domains are graphs. Binding supports concept for references to allow JSON to be used to represent graph information.

  • Each entity is inserted into a single, globally unique location in the JSON with a unique identifier.
  • Each reference is an object of the $type='ref' and must contain value as path to single, globally unique location in the JSON - {$type:'ref',value:['todosById',44]}
{todosById: {"44": {name: "get milk from corner store",done: false,prerequisites: [{$type: "ref",value: ["todosById",54]}]},"54": {name: "withdraw money from ATM",done: false,prerequisites: []}},todos: [{$type: "ref",value: ["todosById",44]},{$type: "ref",value: ["todosById",54]}]};

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.

About

Data binding for react - bindToMixin

Resources

Stars

45 stars

Watchers

3 watching

Forks

Releases

Packages

Used by

Contributors

Languages