Kncokout Create column and rows
by jiggle
HTML
<table>
<tbody data-bind="foreach: rows">
<tr>
<td data-bind="text: id"></td>
<!-- ko foreach: data -->
<td>
<input data-bind="value: value" />
</td>
<!-- /ko -->
</tr>
</tbody>
</table>
<hr>
<fieldset>
<legend><b>Person</b></legend>
<p>New name: <input data-bind="value: newName" /></p>
<p>New age: <input data-bind="value: newAge" /></p>
<button data-bind="click: addRow">Add Row</button>
</fieldset>
<hr>
<fieldset>
<legend><b>Attributes</b></legend>
<p>Name: <input data-bind="value: newAttribute, valueUpdate: 'afterkeydown'" /></p>
<button data-bind="click: addColumn, enable: newAttribute().length">Add Column</button>
</fieldset>
<hr>
<button data-bind="click: save, enable: rows().length > 0">Save to JSON</button>
Last Saved JSON:
<textarea data-bind="value: lastSavedJson" rows="10" cols="60" disabled="disabled"> </textarea>
CSS
td, th { padding: 5px; }
input { width: 75px; }
JavaScript
function Cell(name, value) {
this.name = ko.observable(name);
this.value = ko.observable(value);
}
Cell.prototype.toJSON = function() {
return ko.utils.unwrapObservable(this.value);
}
function Person(id, name, age, additionalColumns) {
var self = this;
self.id = id;
self.data = ko.observableArray([new Cell("name", name), new Cell("age", age)]);
ko.utils.arrayForEach(additionalColumns || [], function(column) {
self.data.push(new Cell(column));
});
}
var lastId=4;
var viewModel = {
rows: ko.observableArray([
new Person(1, "Bob", 44),
new Person(2, "Ted", 22),
new Person(3, "Jane", 55),
new Person(4, "Sue", 11)
]),
addColumn: function() {
var newProperty = this.newAttribute();
ko.utils.arrayForEach(this.rows(), function(row) {
row.data.push(new Cell(newProperty));
});
this.additionalColumns.push(newProperty);
},
additionalColumns: ko.observableArray(),
addRow: function() {
this.rows.push(new Person(++lastId, this.newName(), this.newAge(), this.additionalColumns()));
},
lastSavedJson: new ko.observable(""),
save: function () {
// the problem with this approach is sending unnecessary info
this.lastSavedJson(ko.toJSON(viewModel.rows));
// this won't work as expected
//this.lastSavedJson(ko.utils.stringifyJson(this.rows()));
// and this seems to do the same as above, but better formatted
//this.lastSavedJson(JSON.stringify(viewModel.rows(), null, 2));
},
newName: ko.observable("New Person"),
newAge: ko.observable("20"),
newAttribute: ko.observable("Height")
};
ko.applyBindings(viewModel);