Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

KnockoutJS rendering a table with multiple templates and variable number of columns

I have to render a complex table with variable number of columns. In this example number of columns depends of type of the subRow. For example, if the subRow is type 1, it has 3 actions, if the subRow type is 2, it has 4 actions. Together it is 7 actions, so my table has 7 columns (+ first two where I render subRow name and type (descendant or children etc), but this is less important. these first two columns are always present), so 7+2 = 9 columns. Subrows are added from a tree (not drawn on the example picture, because it's not relevant for this problem).

I made it work in internet explorer, because I'm using font tag to hook on a knockout template to, but Mozilla Firefox and google chrome are not able to render this.

My question is : How to draw this in table, without of font tag?

I wouldn't have anything against some other tag, as long as Firefox an IE can render it, but I tried most of them, and thy don't do the job.

Everything will be much more clear with pseudo code and picture :

HTML :

<table>
<thead>
    <tr>
        <!--

            So this is the table header. It defines number of columns in this table. Number of columns is variable, and this is the first part of the problem. 

        -->
        <th class="tablehead" colspan="2">My List</th><th class="tablehead" data-bind="attr: { colspan: distinctActions().length }"> Actions </th><th class="tablehead"></th>
    </tr>
</thead>  

<tbody>

<tbody data-bind="template: { name: 'rowsTemplate', foreach: rowList } "></tbody>       

</tbody>

Row Template :

<script type="text/x-jquery-tmpl" id="rowsTemplate">
<tr>
    <td>  
        <button data-bind="click: save, enable: editMode()">Save</button>
    </td>
    <td>
        <button data-bind="click: deleteRow, enable: !editMode()">X</button>
    </td>
</tr>

<!-- 

    this is the tricky part
    for each "row" in this template i must repeat X subRows.
    only way I found to do it is to "hook" subRowsTemplate on a  <font> tag.
    BUT the problem is only Internet Explorer is able to render this, neither
    Mozilla Firefox or Chrome are able to do it.

    (Everything MUST be in the same table, because of the 
    variable number of columns (defined in header))

 -->

<font data-bind="template: { name: 'subRowsTemplate', foreach: objectList, templateOptions: { tmpRow: $data } } "></font>

SubRows Template :

</script>   

<script type="text/x-jquery-tmpl" id="subRowsTemplate">
<tr>
    <td> <span data-bind="text: name"></span>  </td>
    <td> 
        <input readonly="readonly" data-bind="visible: selectorList.length>0 && !$item.tmpRow.editMode(), value: chosenSelector().label"></input>
        <select data-bind="visible: selectorList.length>0 && $item.tmpRow.editMode(), options: selectorList, optionsText: 'label', value: chosenSelector"></select>
    </td>

    <!--

        Again the same problem as above, IF subRow IS first, i must draw ALL the actions (defined above in header).
        So, if I have 3 actions defined in header, I must draw 3 <td> here. And again I have the same "solution",
        which doesn't work in Mozilla and Chrome.

    -->     

    <font data-bind="template: { name: 'actionTemplate', foreach: skill, templateOptions: { tmpParentIsFirst: isFirst, tmpObject: $data, tmpRow2: $item.tmpRow } }">  </font>
    <td><div style="float:right;"><button data-bind="click: deleteRow">X</button></div></td>
</tr>

Action Template :

</script>

<script type="text/x-jquery-tmpl" id="actionTemplate">
<td>
    <div>
        Content of action
    </div>
</td>
</script>

Picture :

like image 323
Luka Siric Avatar asked Oct 10 '22 01:10

Luka Siric


1 Answers

Knockout.js 2.0 supports containerless control flow. You can use comment syntax instead and it works with the if, ifnot, foreach, with, and template bindings.

HERE is a working code by the author of the library.

Example:

<ul>
  <li><strong>Here is a static header item</strong></li>
  <!-- ko foreach: products -->
  <li>
    <em data-bind="text: name"></em>
  </li>
  <!-- /ko -->
</ul>

Update:

HERE is a modified customg templateWithOptions binding (original version by Ryan Niemeyer). You can pass options to that will get mapped to each $options property on the input items.

FYI a comment by cs.tropic after he got it running:

after combining all these link and code snippets, my triple foreach template works! crucial thing is, when you use $options, $parent and similar tags, you must not use jquery templates. So now my code is jquery template free

like image 104
kubetz Avatar answered Oct 13 '22 11:10

kubetz