Search code examples
thymeleaf

Creating menu logic with Thymeleaf


I'm trying to dynamically create a menu using basic logic, something like this.

  • List item
    • List item
  • List item
    • List item
    • List item

I made this code

<ul>
    <div data-th-each="field, iter : ${fields}" data-th-remove="tag">
        <div data-th-if="${field.text} != null" data-th-switch="${field.href}" data-th-remove="tag">
            <li data-th-case="null" data-th-utext="${field.text}" >
            <li data-th-case="*"><a data-th-href="${field.href}" data-th-utext="${field.text}" ></a>
        </div>
                <ul data-th-if="${field}"  class="sub-menu">
                    <div data-th-each="prop, propIter : ${field.sub_items.sub_item.properties}" data-th-remove="tag">
                        <div data-th-if="${prop.text} != null" data-th-switch="${prop.href}" data-th-remove="tag">
                            <li data-th-case="null" data-th-utext="${prop.text}"></li>
                            <li data-th-case="*"><a data-th-href="${prop.href}" data-th-utext="${prop.text}"></a></li>
                        </div>
                    </div>
                </ul>
          </li>
    </div>
</ul>

But it returns parsing errors, I think it's mostly a Thymeleaf/HTML problem. It's probably because of the unclosed "li" tags in the switch statement but I'm not sure how to fix it.


Solution

  • Right, it has to be valid html before processing. You can't do any kind of tricks like you have above, even if the output would be valid html.

    I think you should be able to restructure your html to look like this:

    <ul>
        <th:block data-th-each="field, iter : ${fields}" data-th-if="${field.text} != null">
            <li>
                <span data-th-if="${field.href == null}" data-th-utext="${field.text}" />
                <a data-th-unless="${field.href == null}" data-th-href="${field.href}" data-th-utext="${field.text}" />
    
                <ul data-th-if="${field}" class="sub-menu">
                    <th:block data-th-each="prop, propIter : ${field.sub_items.sub_item.properties}" data-th-if="${prop.text} != null">
                        <span data-th-if="${prop.href == null}" data-th-utext="${prop.text}" />
                        <a data-th-unless="${prop.href == null}" data-th-href="${prop.href}" data-th-utext="${prop.text}" />
                    </th:block>
                </ul>
            </li>
        </th:block>
    </ul>
    

    I've never though about using data-th-remove="tag" like you have. But I think you should be using <th:block> instead for cases like this.