Git Product home page Git Product logo

reactive's Introduction

reactive

Reactive template engine for robust real-time rendering of model data changes.

Installation

With component:

$ component install component/reactive

With the stand-alone browser build:

<script src="reactive.js"></script>

API

reactive(element, object, [view])

Bind object to the given element with optional view object. When a view object is present it will be checked first for overrides, which otherwise delegate to the model object.

For example if you have the following HTML:

<h1 data-text="name"></h1>

And pass the following object as the second argument:

{
  name: 'Tobi'
}

The output will become:

<h1>Tobi</h1>

However if you wish to manipulate the output or provided computed properties thae view object may be passed. For example an object of:

{
  first_name: "Tobi",
  last_name: "Ferret"
}

And a view of:

function UserView(user) {
  this.user = user;
}

UserView.prototype.name = function(){
  return this.user.first_name + ' ' + this.user.last_name;
}

Would produce:

<h1>Tobi Ferret</h1>

Typically a view object wraps a model to provide additional functionality, this may look something like the following:

function UserView(user) {
  this.user = user;
  this.el = reactive(tmpl, user, this);
}

UserView.prototype.name = function(){ ... }

Often a higher-level API is built on top of this pattern to keep things DRY but this is left to your application / other libraries.

Adapters

Subscriptions

Subscriptions allow reactive to know when an object's data has changed updating the DOM appropriately without re-rendering a static template. This means if you make manual DOM adjustments, append canvases etc they will remain intact.

By default reactive subscribes using .on("change <name>", callback) however it's easy to define your own subscription methods:

reactive.subscribe(function(obj, prop, fn){
  obj.bind(prop, fn);
});

reactive.unsubscribe(function(obj, prop, fn){
  obj.unbind(prop, fn);
});

Getting and Setting

You can make reactive compatible with your favorite framework by defining how reactive gets and sets the model.

By default reactive supports obj[prop] = val and obj[prop](val), but these can be changed with reactive.get(fn) and reactive.set(fn). Here's how to make reactive compatible with backbone:

reactive.get(function(obj, prop) {
  return obj.get(prop);
});

reactive.set(function(obj, prop, val) {
  obj.set(prop, val);
});

Interpolation

Bindings may be applied via interoplation on attributes or text. For example here is a simple use of this feature to react to changes of an article's .name property:

<article>
  <h2>{name}</h2>
</article>

Text interpolation may appear anywhere within the copy, and may contain complex JavaScript expressions for defaulting values or other operations.

<article>
  <h2>{ name || 'Untitled' }</h2>
  <p>Summary: { body.slice(0, 10) }</p>
</article>

Reactive is smart enough to pick out multiple properties that may be used, and react to any of their changes:

<p>Welcome { first + ' ' + last }.</p>

Interpolation works for attributes as well, reacting to changes as you'd expect:

<li class="file-{id}">
  <h3>{filename}</h3>
  <p><a href="/files/{id}/download">Download {filename}</a></p>
<li>

Declarative Bindings

By default reactive supplies bindings for setting properties, listening to events, toggling visibility, appending and replacing elements. Most of these start with "data-*" however this is not required.

data-text

The data-text binding sets the text content of an element.

data-html

The data-html binding sets the inner html of an element.

data-

The data-<attr> bindings allows you to set an attribute:

<a data-href="download_url">Download</a>

on-

The on-<event> bindings allow you to listen on an event:

<li data-text="title"><a on-click="remove">x</a></li>

data-append

The data-append binding allows you to append an existing element:

<div class="photo" data-append="histogram">

</div>

data-replace

The data-replace binding allows you to replace an existing element:

<div class="photo" data-replace="histogram">

</div>

data-{show,hide}

The data-show and data-hide bindings conditionally add "show" or "hide" classnames so that you may style an element as hidden or visible.

<p data-show="hasDescription" data-text="truncatedDescription"></p>

data-checked

Toggles checkbox state:

<input type="checkbox" data-checked="agreed_to_terms">

Writing bindings

To author bindings simply call the reactive.bind(name, fn) method, passing the binding name and a callback which is invoked with the element itself and the value. For example here is a binding which removes an element when truthy:

reactive.bind('remove-if', function(el, name){
  el = $(el);
  var parent = el.parent();
  this.change(function(){
    if (this.value(name)) {
      el.remove();
    }
  });
});

Computed properties

Reactive supports computed properties denoted with the < character. Here the fullname property does not exist on the model, it is a combination of both .first and .last, however you must tell Reactive about the real properties in order for it to react appropriately:

<h1 data-text="fullname < first last"></h1>

NOTE: in the future Reactive may support hinting of computed properties from outside Reactive itself, as your ORM-ish library may already have this information.

Interpolation

Some bindings such as data-text and data-<attr> support interpolation. These properties are automatically added to the subscription, and react to changes:

<a data-href="/download/{id}" data-text="Download {filename}"></a>

Notes

Get creative! There's a lot of application-specific logic that can be converted to declarative Reactive bindings. For example here's a naive "auto-submit" form binding:

<div class="login">
  <form action="/user" method="post" autosubmit>
    <input type="text" name="name" placeholder="Username" />
    <input type="password" name="pass" placeholder="Password" />
    <input type="submit" value="Login" />
  </form>
</div>
var reactive = require('reactive');

// bind

var view = reactive(document.querySelector('.login'));

// custom binding available to this view only

view.bind('autosubmit', function(el){
  el.onsubmit = function(e){
    e.preventDefault();
    var path = el.getAttribute('action');
    var method = el.getAttribute('method').toUpperCase();
    console.log('submit to %s %s', method, path);
  }
});

For more examples view the ./examples directory.

License

MIT

reactive's People

Contributors

anthonyshort avatar edef1c avatar ianstormtaylor avatar karlbohlmark avatar luka5 avatar matthewmueller avatar stereosteve avatar timoxley avatar tj avatar tonistiigi avatar tootallnate avatar vendethiel avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.