Knockout.js repeat rows in table for nested model / containerless “foreach” inside table
http://stackoverflow.com/questions/9731282/knockout-js-repeat-rows-in-table-for-nested-model-containerless-foreach-insi
HTML
<script src="https://github.com/downloads/SteveSanderson/knockout/knockout-2.0.0.debug.js"></script>
<script src="http://elboyero.oestedatos.com/deco.oestedatos.com/scripts/productos.js"></script>
<table>
<thead>
<tr>
<th> </th>
<th>Producto</th>
<th>Modelo / Descripción</th>
<th>Cantidad</th>
<th>Unitario</th>
<th>Mano de Obra</th>
<th>Género</th>
</tr>
</thead>
<tbody data-bind='foreach: lineas'>
<tr>
<td>
<button data-bind="click: $parent.removerLinea">-</button>
</td>
<td>
<select data-bind='options: productos, optionsText: "nombre", optionsCaption: "Seleccione...", value: producto'> </select>
</td>
<td data-bind="with: producto">
<select data-bind='options: modelos, optionsText: "nombre", optionsCaption: "Seleccione...", value: $parent.modelo'></select>
</td>
<td><input data-bind="visible: modelo, value: cantidad, valueUpdate: 'afterkeydown'" class="small" /></td>
<td><input data-bind="visible: modelo, value: unitario, valueUpdate: 'afterkeydown'" class="small" /></td>
<td><span data-bind="text: formatCurrency(mano_obra())"></span></td>
<td><button data-bind="visible: modelo, click: agregarGenero">+</button></td>
</tr>
<!-- ko data-bind='foreach: generos' -->
<tr>
<td>
<button data-bind="click: remover">-</button>
</td>
<td>Genero</td>
<td><input type="text" data-bind="value: descripcion" /></td>
<td><input type="text" class="small" data-bind="value: cantidad" /></td>
<td><input...
JavaScript
function formatCurrency(value) {
return "$" + value.toFixed(2);
}
//The customization line class
var LineaGenero = function() {
var self = this;
self.producto = ko.observable('Genero');
self.descripcion = ko.observable('');
self.cantidad = ko.observable(1);
self.unitario = ko.observable(0);
self.subtotal = ko.computed(function() {
return self.cantidad() * parseInt(self.unitario());
});
//removes itself from the parent product line
self.remover = function(linea){
linea.removerGenero(self);
}
};
//The product line class
var LineaPedido = function() {
var self = this;
self.producto = ko.observable();
self.modelo = ko.observable();
self.cantidad = ko.observable(1);
self.unitario = ko.observable(0);
self.mano_obra = ko.computed(function() {
return self.cantidad() * parseInt(self.unitario());
});
self.generos = ko.observableArray();
// Whenever the category changes, reset the product selection
self.producto.subscribe(function() {
self.modelo(undefined);
});
self.modelo.subscribe(function(nuevoModelo){
//Suggest the product price
self.unitario(nuevoModelo.precio);
});
//Add customization line
self.agregarGenero = function() {
self.generos.push(new LineaGenero());
};
//Remove customization line
self.removerGenero = function(genero) {
self.generos.remove(genero);
};
};
...