2

Essentially I have the following 2 dimensional array:

"items": 
[
    ["",""],
    ["",""],
    ["",""]
]

I want to iterate over this collection using knockout and I got the following:

        <!-- ko foreach: items -->
        <tr>
            <td>
                <button type="button" class="btn btn-default btn-xs"><i class="fa fa-plus"></i> Column</button>
            </td>
            <!-- ko foreach: $data -->
            <td>
                <input type="text" class="form-control" data-bind="value: $data" />
            </td>
            <!-- /ko -->
        </tr>
            <!-- /ko -->

However, this does not appear to be working. Any ideas?

Thanks in advance

G

1
  • You'll need to update your question to include how you are applying your knockout bindings. Best to create a fiddle so you can replicate your issue. Commented Feb 4, 2014 at 18:13

2 Answers 2

4

Virtual bindings are just comments and sometimes can get moved around by the browser as it tries to correct the HTML markup. In this case, the browser surrounds your <tr> tag with a <tbody> tag as required by the HTML spec. The <tbody> starts right before the <tr> tag and ends right before the closing </table> tag. Thus the virtual element closing comment is now in the wrong place:

<table>
    <!-- ko foreach: items -->
    <tbody>
        <tr>
            ...
        </tr>
        <!-- /ko -->
    </tbody>
</table>

The key to fixing this is to add the <tbody> tag to your markup:

<table>
    <tbody>
        <!-- ko foreach: items -->
        <tr>
            ...
        </tr>
        <!-- /ko -->
    </tbody>
</table>

Reference: http://www.whatwg.org/specs/web-apps/current-work/multipage/tree-construction.html#parsing-main-intable

Sign up to request clarification or add additional context in comments.

Comments

0

You've run into an edge case where Knockout isn't able to find the second <!-- /ko --> tag when it's inside of a <table>.

The following markup causes an error (in Chrome it's saying Uncaught Error: Cannot find closing comment tag to match: ko foreach: items):

<table>
<!-- ko foreach: items -->
        <tr>
            <td>
                <button type="button" class="btn btn-default btn-xs"><i class="fa fa-plus"></i> Column</button>
            </td>
            <!-- ko foreach: $data -->
            <td>
                <input type="text" class="form-control" data-bind="value: $data" />
            </td>
            <!-- /ko -->
        </tr>
<!-- /ko -->
</table>

Fiddle: http://jsfiddle.net/63rkQ/

But if you change the outer foreach to be on the <table> tag, it works:

<table data-bind="foreach: items">
        <tr>
            <td>
                <button type="button" class="btn btn-default btn-xs"><i class="fa fa-plus"></i> Column</button>
            </td>
            <!-- ko foreach: $data -->
            <td>
                <input type="text" class="form-control" data-bind="value: $data" />
            </td>
            <!-- /ko -->
        </tr>
</table>

Fiddle: http://jsfiddle.net/63rkQ/1/

Try not to use virtual elements for your bindings unless you absolutely have to. I've run into strange cases where they work on some browsers but not others. They're difficult to debug.

You can see that moving the virtual element outside of the <table> also works (at least in Chrome) but I don't think that's what you wanted)...

Fiddle: http://jsfiddle.net/63rkQ/2/

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.