Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Knockout Error: Cannot find closing comment tag to match

This may seem like a duplicate question, but none of the other answers have helped me. I have the following HTML (it's a Razor template, but no Razor specifics here).

<p class="search-results-summary">
    Results 
    <!-- ko if: SearchTerms.Query -->
    for <span data-bind="html: SearchTerms.Query"></span>
    <!-- /ko -->
    <!-- ko if: SearchTerms.Names -->
    for Names <span data-bind="html: SearchTerms.Names.join(', ')"></span>
    <!-- /ko -->
    <!-- ko if: SearchTerms.Location && AlternativeLocations && AlternativeLocations.length -->
        within <span data-bind="text: SearchTerms.LocationRadio"></span>
        miles of <span data-bind="html: SearchTerms.Location"></span>. 
        <!-- ko if: AlternativeLocations && AlternativeLocations.length > 1 -->
            <a class="more alternative-locations" href="#">more</a>
            <ul id="other-location-matches" data-bind="foreach: AlternativeLocations.slice(1).sort()" style="display: none">
                <li>&gt; Did you mean <a data-bind="html: $data, attr: { href: Edge.API.CurrentSearchResponse.SearchTerms.mutate({ Location: $data }).getUrl() }"></a>?</li>
            </ul>
        <!-- /ko -->
    <!-- /ko -->
    <!-- ko if: SearchTerms.Location && (!AlternativeLocations || AlternativeLocations.length == 0) -->
    <span class="error">We couldn't find '<span data-bind="html: SearchTerms.Location"></span>' on the map. Your search ran Worldwide.
    </span>
    <!-- /ko -->
</p>

When I try to bind this template using Knockout, I get this error:

Error: Cannot find closing comment tag to match: ko if: SearchTerms.Location && AlternativeLocations && AlternativeLocations.length 

I have tried:

  • Upgrading Knockout from 2.2.1 to 2.3.0. No use
  • Verifying HTML/XML structure. It's good!
  • Removing the <ul id="other-location-matches"...> seems to get rid of the issue... but I need that <ul>!!

Any ideas? Am I looking at a Knockout.js bug?

like image 405
Mauricio Morales Avatar asked Sep 10 '13 20:09

Mauricio Morales


2 Answers

I have encountered the same issue except with table tags.

Doesn't work - produces the same issue as indicated by Mauricio

<table>
<!-- ko: foreach: { data: SomeData, as: 'item' } -->
   <tr>
      <td data-bind="text: item"></td>
   </tr>
<!-- /ko -->
</table>

Works:

<table>
   <tbody>
   <!-- ko: foreach: { data: SomeData, as: 'item' } -->
      <tr>
         <td data-bind="text: item"></td>
      </tr>
   <!-- /ko -->
   </tbody>
</table>
like image 119
Sash Avatar answered Nov 09 '22 12:11

Sash


Short answer:

HTML doesn't allow block element inside P element. So the P element is closed right before the UL element. The ko comment open tag end in the P element and the closing tag outside. Knockout require both open and closing comment tag to be in the same element.


Original answer:

thanks to @Sash, I've understood why the <tbody> tag is mandatory.

I was having the same problem with this piece of html:

<table>
    <thead>
        <th>ID
        <!-- ko if: showName() --> <th>Name <!-- /ko -->
    <tbody data-bind="foreach: data">
...

Obviously, it doesn't work for the same reason. Why it doesn't work striked me when I added </th> until it work. I needed to add the closing tag before the opening ko comment. As soon I have seen that, I recalled SGML 101. Optional tag come after comment. So the actual DOM tree look like that for my code:

─┬─Table
 ├─┬─THead
 │ ├─┬─Th
 │ | ├─#Data(ID)
 │ | └─#Comment(ko if:)
 │ └─┬─Th
 │   ├─#Data(Name)
 │   └─#Comment(/ko)
 └─┬─TBody
   ┊

You can notice the opening and closing tag are on two branch of the node tree. To get the comment at the right position, optionnal tag need to be explictely placed. @michael best explain why this affect the original poster.

like image 21
gkr Avatar answered Nov 09 '22 14:11

gkr