Knockoutjs.com - Grid editor example
http://knockoutjs.com/examples/gridEditor.html
HTML
<script src="http://knockoutjs.com/js/jquery.tmpl.js"></script>
<script src="http://knockoutjs.com/js/jquery.validate.js"></script>
<script src="http://cloud.github.com/downloads/SteveSanderson/knockout/knockout-1.2.1.js"></script>
<div class='liveExample'>
<form action='/someServerSideHandler'>
<p>You have asked for <span data-bind='text: gifts().length'> </span> gift(s)</p>
<table data-bind='visible: gifts().length > 0'>
<thead>
<tr>
<th>Gift name</th>
<th>Price</th>
<th />
</tr>
</thead>
<tbody data-bind='template: { name: "giftRowTemplate", foreach: gifts }' />
</table>
<button data-bind='click: addGift'>Add Gift</button>
<button data-bind='enable: gifts().length > 0' type='submit'>Submit</button>
</form>
<script id='giftRowTemplate' type='text/html'>
<tr>
<td><input class='required' data-bind='value: name, uniqueName: true' /></td>
<td><input class='required number' data-bind='value: price, uniqueName: true' /></td>
<td><a href='#' data-bind='click: function() { viewModel.removeGift($data) }'>Delete</a></td>
</tr>
</script>
</div>
CSS
body { font-family: arial; font-size: 14px; }
.liveExample { padding: 1em; background-color: #EEEEDD; border: 1px solid #CCC; max-width: 655px; }
.liveExample input { font-family: Arial; }
.liveExample b { font-weight: bold; }
.liveExample p { margin-top: 0.9em; margin-bottom: 0.9em; }
.liveExample select[multiple] { width: 100%; height: 8em; }
.liveExample h2 { margin-top: 0.4em; font-weight: bold; font-size: 1.2em; }
.liveExample table, .liveExample td, .liveExample th { padding: 0.2em; border-width: 0; }
.liveExample td input { width: 13em; }
tr { vertical-align: top; }
.liveExample input.error { border: 1px solid red; background-color: #FDC; }
.liveExample label.error { display: block; color: Red; font-size: 0.8em; }
.liveExample th { font-weight: bold; }
li { list-style-type: disc; margin-left: 20px; }
JavaScript
var Gift = function (config) {
this.name = ko.observable(config.name);
this.price = ko.observable(config.price);
};
var viewModel = {
gifts: ko.observableArray([
new Gift({
name: "Tall Hat",
price: "39.95"}),
new Gift({
name: "Long Cloak",
price: "120.00"})
]),
addGift: function() {
this.gifts.push(new Gift({
name: "",
price: ""
}));
},
removeGift: function(gift) {
this.gifts.remove(gift);
},
save: function(form) {
alert("Could now transmit to server: " + ko.utils.stringifyJson(this));
alert(ko.toJSON(this));
alert(ko.utils.stringifyJson(ko.utils.unwrapObservable(this)));
alert(ko.utils.stringifyJson(ko.utils.unwrapObservable(this.gifts)));
ko.utils.postJson($("form")[0], this.gifts);
}
};
ko.applyBindings(viewModel);
$("form").validate({
submitHandler: function() {
viewModel.save()
}
});