Facundo Farias
Facundo Farias

Reputation: 408

Knockout.js repeat rows in table for nested model / containerless "foreach" inside table

I’m building an application to track orders of tailor made products. Each product can have many custom details. The screen to add products to an order and customize each one should look like this:

<button>+</button><!-- "Add new product line" button -->
<table>
    <thead>
        <tr>
            <th></th>
            <th>Producto</th><!-- The product category or type -->
            <th>Modelo</th><!-- The product -->
            <th>Cantidad</th><!-- Quantity -->
            <th>Unitario</th><!-- Unit Price -->
            <th>Mano de Obra</th><!-- The price of the product itself -->
            <th>Genero</th><!-- The price of the customization -->
        </tr>
    </thead>
    <tbody>
        <tr class="producto"><!-- Product line -->
            <td><button>-</button></td><!-- "Remove" button, should remove the product and it's customizations -->
            <td><select>Producto</select></td><!-- Choose category -->
            <td><select>Modelo</select></td><!-- Choose product -->
            <td><input type="text" class="cantidad" /></td><!-- Enter quantity -->
            <td><input type="text" class="unitario" /></td><!-- Enter unit price -->
            <td>$ <span class="mano_obra"></span></td><!-- Line total. The product lines calculates on this column -->
            <td><button>+</button></td><!-- "Add customization" button. Should add a line like the next <tr> -->
        </tr>
        <tr class="genero"><!-- Customization line -->
            <td><button>-</button></td><!-- "Remove" button, should remove only this customization line -->
            <td>Genero</td><!-- Fixed text -->
            <td><input type="text" class="genero" /></td><!-- Enter customization description -->
            <td><input type="text" class="cantidad" /></td><!-- Enter quantity -->
            <td><input type="text" class="unitario" /></td><!-- Enter unit price -->
            <td>&nbsp;</td><!-- On customizations, this column is empty -->
            <td>$ <span class="genero"></span></td><!-- Line total. The customizations calculates on this column -->
        </tr>
        <tr class="genero">
            <!-- Another customization for the first product -->
        </tr>
        <tr class="genero">
            <!-- Another one -->
        </tr>
        <tr class="producto">
            <!-- A different product -->
        </tr>
        <tr class="genero">
            <!-- The new product customization -->
        </tr>
        <!-- (etc) -->
    </tbody>
    <tfoot>
        <tr>
            <td colspan="5">Subtotales</td><!-- Fixed text -->
            <td>$ <span class="subtotal_mano_obra"></span></td><!-- SUM of each line total, for products -->
            <td>$ <span class="subtotal_genero"></span></td><!-- SUM of each line total, for customizations -->
        </tr>
    </tfoot>
</table>

I've tried to do this:

<tbody data-bind='foreach: lineas_pedido'>
    <tr class="producto">
        <!-- All the bindings here works fine -->
    </tr>
    <!-- ko foreach: generos -->
    <tr class="genero">
        <!-- ... -->
    </tr>
    <!-- /ko -->
</tbody>

But after getting errors and looking, came to this: Knockout.js containerless "foreach" not working with <table>

So, I found this plugin: https://github.com/mbest/knockout-repeat And now my code looks like this:

<tbody data-bind='foreach: lineas_pedido'>
    <tr class="producto">
        <!-- All the bindings here works fine -->
    </tr>
    <tr class="genero" data-bind="repeat: {foreach: generos, item: '$genero'}">
        <!-- ... -->
    </tr>
</tbody>

My question is: Is there any way to avoid using the plugin, and accomplish the same result using native KO templating/bindings?

Thanks in advance.

Edit:

Here is the jsfiddle, I've added a resource linking to my sample data (categories and products).

Here is the actual code on my testing host.

Also, I've used this example as the start point.

Upvotes: 0

Views: 3944

Answers (1)

antishok
antishok

Reputation: 2910

I've spotted 3 errors in your fiddle. pretty sure I didn't break any logic but it'd be easier if I knew spanish :) Updated fiddle with fixes here: http://jsfiddle.net/antishok/cxLRs/

  1. data-bind is not supposed to appear here: <!-- ko data-bind='foreach: generos' -->

  2. You had a "click: remover" binding which called LineaGenero.remover, which expects a LineaPedido which is the parent to remove from. But the actual argument was the current LineaGenero, not its parent. The correct approach here is the same as you did with the binding "click: $parent.removerLinea"

  3. You had this line: self.modelo(undefined); which triggered the self.modelo subscription handler. There was no check in there for the undefined value, causing errors.

Upvotes: 3

Related Questions