Features
- paging with build in pager, could be replaced
- sorting by click headers, user defined function is also supported
- filter filter with string or your filter function
- Local/Remote mode both supported, could be switched easily
- formatter/render define your reusable function for data rendering
- data reactive automatically reative the change on data
- Event delegation improve the performance and get the desired data easily
Play with it
<table>
<thead>
<tr>
<th class="sort" data-sort="name">name</th>
<th class="sort" data-sort="age">age</th>
<th class="sort" data-sort="score">score</th>
<th class="sort" data-sort="percent">percentage</th>
<th class="sort" data-sort="money">money</th>
<th>active</th>
<th>action</th>
</tr>
</thead>
<tbody>
<tr>
<td class="left">{name}</td>
<td>{age}</td>
<td>{score | currency 0}</td>
<td>{percent | percentage}</td>
<td react="money" class="money">¥{money | currency 2}</td>
<td react="isActive" data-render="setActive" class="center"></td>
<td><button class="save" react="$stat">save</button></td>
</tr>
</tbody>
</table>
var grid = new Grid(template, {
perpage: 10,
filters: {
percentage: function (val) {
return (val*100).toFixed() + '%'
}
},
bindings: {
react: function (prop) {
this.bind('$stat', function (model, el) {
var changed = model.changed()
if (prop === '$stat') {
el.disabled = changed === false ? true : false
} else {
if (changed && changed.hasOwnProperty(prop)) {
classes(el).add('dirty')
} else {
classes(el).remove('dirty')
}
}
})
}
},
delegate: {
setActive: function (model, el) {
el.innerHTML = ''
var cb = document.createElement('input')
cb.type = 'checkbox'
cb.checked = model.isActive
cb.addEventListener('change', function () {
// save value to model
model.isActive = cb.checked
}, false)
el.appendChild(cb)
}
}
})
grid.local()
placeholder.appendChild(grid.el)
grid.setData(data)
grid.bind('click', 'button.save',function (e, model) {
if (e.delegateTarget.disabled) return
var changed = model.changed()
overlay.show()
var s = spin(overlay.el).text('saving')
if (changed) {
setTimeout(function () {
s.remove()
overlay.hide()
Notice('saved', {
type: 'success',
closable: false,
duration: 2000
})
// mark model as clean
model.clean()
}, 400)
}
})
grid.bind('click', 'td.money',function (e, model) {
var el = e.target
el.innerHTML = '<input style="width:100%;" type="number" required min="0.00" value="' + model.money + '">'
var input = el.children[0]
input.focus()
var save = function () {
var v = Number(input.value)
model.money = v
}
input.addEventListener('keyup', function (e) {
if (e.which === 13) {
input.blur()
}
})
input.addEventListener('blur', save)
})
{
"_id": "561eb4e2ebd3da83cca919cd",
"index": 0,
"guid": "e4a3c415-cc1e-4ea2-ac51-643ab7682749",
"isActive": false,
"balance": "$1,973.10",
"picture": "http://placehold.it/32x32",
"age": 25,
"eyeColor": "green",
"name": "Beth Henderson",
"gender": "female",
"company": "COMTRACT",
"email": "bethhenderson@comtract.com",
"phone": "+1 (812) 525-3569",
"address": "557 Hinckley Place, Baker, Rhode Island, 109",
"score": 7472,
"money": 3286.94,
"percent": 0.4786
}
tips: click headers to sort, change money by click