composable, reactive dom elements with sparse rendering

Usage no npm install needed!

<script type="module">
  import morphable from '';



composable, reactive dom elements with sparse rendering

npm install morphable

powered by observer-util, nanomorph, and on-load. built for use with bel.


a list of random numbers that are randomized on click.

ul reacts to changes to list and each li reacts to changes to an element of list, sparsely. that is, mutating list[0].number will only re-render the first list item in the dom.

const html = require('bel')
const _ = require('morphable')

const list = _([ { number: Math.random() } ])

const li = _(item => html`<li onclick=${randomize.bind(item)}>${item.number}</li>`)
const ul = _(list => html`<ul>${}</ul>`)

document.body = html`<body>
  <button onclick=${append.bind(list)}>
    Add a random number

function append () {
  this.push({ number: Math.random() })

function randomize () {
  this.number = Math.random()

try running budo example.js using budo


let _ = require('morphable')

let state = _({})
let view = _(state => dom_element)
let element = view(state)

element morphs when state that it depends upon changes.

you can subscribe to load, premorph, morph, and unload events on view.

view.on('load', () => console.log('loaded element'))
view.on('premorph', () => console.log('element, just before morph'))
view.on('morph', () => console.log('morphed element'))
view.on('unload', () => console.log('unloaded element'))

elements start and stop reacting to changes when they are added to and removed from the dom.

browser support

morphable uses proxies, supported in all modern browsers. proxies are not supported by internet explorer, however there is a partial polyfill. see this fork that makes this library usable in IE11.

using the partial polyfill requires limiting one's use of proxies to features supported by the polyfill. namely, only using only get, set, apply, and construct traps and restricting use to properties defined at proxy creation time. handling arrays is challenging for this reason. the fork patches array mutations, so anticipate performance hits. that said, if you're not doing anything too crazy, you'll probably be fine.