JSFiddle - React, Tailwind, and code Playground
HTML
<script src="//unpkg.com/ractive"></script>
<div id='container'></div>
<script id='tpl' type='text/ractive'>
<table>
<thead>
<tr><th>Width</th><th>Height</th><th>Area</th></tr>
</thead>
<tbody>
{{#boxes}}
<tr><td>{{width}}</td><td>{{height}}</td><td>{{area}}</td></tr>
{{/boxes}}
</tbody>
</table>
<table>
<thead>
<tr><th>Width</th><th>Height</th><th>Area</th></tr>
</thead>
<tbody>
{{#boxes}}
<tr><td><input type='number' value='{{width}}'></td><td><input type='number' value='{{height}}'></td><td>{{area}}</td></tr>
{{/boxes}}
</tbody>
</table>
</script>
CSS
body {
font-family: 'Helvetica Neue', 'Arial';
font-size: 16px;
color: #353535;
}
table {
border-spacing: 0;
margin: 0 0 2em 0;
}
th {
background-color: #eee;
}
td, th {
border-bottom: 1px solid #eee;
padding: 0.2em 1em;
width: 6em;
text-align: right;
}
td {
}
input[type="number"] {
font-size: inherit;
font-family: inherit;
width: 3.5em;
text-align: right;
padding: 0;
}
JavaScript
var littleBox, mediumBox, bigBox, ractive, Box, boxAdaptor;
Box = function ( width, height ) {
this.width = width;
this.height = height;
};
Box.prototype = {
getArea: function () {
return this.width * this.height;
},
setWidth: function ( width ) {
this.width = width;
},
setHeight: function ( height ) {
this.height = height;
}
};
boxAdaptor = {
// Ractive uses the `filter` function to determine whether something
// needs to be wrapped or not. For example 'boxes' doesn't need to be
// wrapped because it's an array, but 'boxes.0' - which is the same as
// our `littleBox` variable - does.
filter: function ( object ) {
return object instanceof Box;
},
// If an object passes the filter, we wrap it.
wrap: function ( ractive, box, keypath, prefixer ) {
// We can simply overwrite the prototype methods with ones that
// do the same thing, but also notify Ractive about the changes
box.setWidth = function ( width ) {
this.width = width;
// Very often, inside adaptors, we need to turn _relative keypaths_
// into _absolute keypaths_. For example if this box's keypath is
// 'boxes.0', we need to turn 'width' and 'area' into 'boxes.0.width'
// and 'boxes.0.area'.
//
// This is such a common requirement that a helper function -
// `prefixer` - is automatically generated for each wrapper.
ractive.set( prefixer({
width: width,
area: box.getArea()
}));
};
box.setHeight = function ( height ) {
this.height = height;
ractive.set( prefixer({
height: height,
area: box.getArea()
}));
};
// The wrapper we return is used by Ractive to interact with each box.
...