Search code examples
javascriptjqueryknockout.jsknockout-mvc

Remove button UI issue inside nested templates - Knockout.js


I'm in a bit of trouble from good 20 hours now. I am using knockout.js and dynamically add/remove rows from html table. I am having trouble in displaying an extra column for the remove button dynamically, my template is:

 <table class="tg">
    <tbody data-bind="template: {name: 'LineItemsBodyScript', foreach: LineItemFields, afterRender: addRowRemoveButton}"></tbody>
</table>

 //template that gets called from HTML table.
 <script id="LineItemsBodyScript" type="text/html">
    <!-- ko ifnot: isFirsElement($index) -->
        <tr data-bind="template: {name: 'LineItemDataTemplate', foreach: $data }"></tr>
    <!-- /ko -->
</script>

//template called inside the template
<script id="LineItemDataTemplate" type="text/html">
       <td><input type="text" data-bind="value: FieldValue, visible: IsVisible, enable: IsUpdatable" class="table-column" /></td>
</script>

If i add remove button in 'LineItemDataTemplate' template, it renders the remove button after every column (makes sense). And if i add remove button in 'LineItemsBodyScript', it gets overwritten by the child template. My model is, List>. How and where could i add the remove button?

 <td><input type='button' value="Remove" /></td> 

I looked around and found afterRender afterAdd methods but they are not going to solve the issue. Note: No. of columns are unknown (therefore i made a generic class for Column-Name & Column-Value)


Solution

  • You can add an extra <td> in the LineItemDataTemplate template when it's being rendered for the last field (grootboek) for each row that is not the header row:

    • Last field when: $index() == $parentContext.$data.length - 1

    • Not header row (first row): $parentContext.$index() > 0

    Which results in:

    <script id="LineItemDataTemplate" type="text/html">
        <td><input type="text"
                   data-bind="value: FieldValue, visible: IsVisible,
                              enable: IsUpdatable" 
                   class="table-column" /></td>
        <!-- ko if: $parentContext.$index() > 0 
                    && $index() == $parentContext.$data.length - 1 -->
        <td>
            <button data-bind="click: removeLineItem">Remove</button>
        </td>
        <!-- /ko -->
    </script>