Given the following model and view model for nested categories:
function Category(id, name) {
var self = this;
self.Id = ko.observable(id || '00000000-0000-0000-0000-000000000000');
self.Name = ko.observable(name);
self.children = ko.observableArray();
self.addCategory = function () {
self.children.push(new Category("", ""));
};
self.removeCategory = function(category) {
self.children.remove(category);
};
}
var CategoryManagerViewModel = function() {
var self = this;
self.children = ko.observableArray();
self.addCategory = function () {
self.children.push(new Category("", ""));
};
self.removeCategory = function (category) {
self.children.remove(category);
};
self.save = function() {
self.lastSavedJson(JSON.stringify(ko.toJS(self.children), null, 2));
};
self.lastSavedJson = ko.observable("");
};
I am trying to figure out how to create a template that can adapt as more child categories are nested within each other. Currently, my template looks like this:
<table class='categoriesEditor'>
<tr>
<th>Category</th>
<th>Children</th>
</tr>
<tbody data-bind="foreach: children">
<tr>
<td>
<input data-bind='value: Name' />
<div><a href='#' style="color:black" data-bind='click: removeCategory'>Delete</a></div>
</td>
<td>
<table>
<tbody data-bind="foreach: children">
<tr>
<td><input data-bind='value: Name' /></td>
<td><a href='#' style="color:black" data-bind='click: removeCategory'>Delete</a></td>
<td>
<table>
<tbody data-bind="foreach: children">
<tr>
<td><input data-bind='value: Name' /></td>
<td><a href='#' style="color:black" data-bind='click: removeCategory'>Delete</a></td>
</tr>
</tbody>
</table>
<a href='#' style="color:black" data-bind='click: addCategory'>Add cat</a>
</td>
</tr>
</tbody>
</table>
<a href='#' style="color:black" data-bind='click: addCategory'>Add cat</a>
</td>
</tr>
</tbody>
</table>
</div>
<p>
<button data-bind='click: addCategory'>Add root category</button>
<button data-bind='click: save, enable: children().length > 0'>Save to JSON</button>
</p>
This currently allows for 3 levels of nesting within categories, but what if I need more levels? Do I simply copy and paste the markup? It feels like there should be a better way.
Update:
The binding is set up as follows:
var viewModel = new CategoryManagerViewModel();
viewModel.addCategory();
ko.applyBindings(viewModel);