npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

react-binding

v0.9.1

Published

Binder - react two-way data binding for complex objects and arrays.

Downloads

1,052

Readme

react-binding

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

import React from 'react';
import ReactDOM from 'react-dom';
import Binder from 'react-binding';

export default class Form extends React.Component {
  constructor(props){
    super(props);
    this.state = {data: {}};
  },
  render {
    return (
      <div>
        <input valueLink={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

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 ReactDOM from 'react-dom';
import Binder from 'react-binding';

export default class Form extends React.Component {
  constructor(props){
    super(props);
    this.state = {data: {}};
  },
  render {
    return (
      <div>
        <input valueLink={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 [email protected]

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(this,"data","Employee")} />
  <PersonComponent personModel={Binder.bindToState(this,"data","Deputy")} />
  • binding to parent
  <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.

  • binding to array
    <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.

  • binding to array
    <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

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.