【问题标题】:How to render menu using thymeleaf recursively如何递归地使用thymeleaf 渲染菜单
【发布时间】:2014-07-30 09:09:20
【问题描述】:

我想使用 ul/li 列表呈现 HTML 菜单。我有这个类结构:

public class MenuItem {

    private String name;

    private MenuItem parent;

    private List<MenuItem> children;

    public MenuItem(String name,List<MenuItem> children) {
        this.name = name;
        this.children = children;
        for (MenuItem child : children) {
            child.parent = this;
        }
    }

    public MenuItem(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public MenuItem getParent() {
        return parent;
    }

    public List<MenuItem> getChildren() {
        return children;
    }
} 

如您所见,它是典型的树形结构,其中一个根元素包含对其子元素的引用,而它们又对其子元素的引用,依此类推。

现在我想渲染这样的结构:

<ul>
    <li>Item 1
        <ul>
            <li>Item 1.1</li>
            <li>Item 1.2
                <ul>
                    <li>Item 1.2.1</li>
                    <li>Item 1.2.3</li>
                </ul>
            </li>
            <li>Item 1.3</li>
        </ul>
    </li>
    <li>Item 2</li>
</ul>

我怎样才能用百里香来做到这一点?如果我必须使用 其他技术,例如 Tiles、Layout 或其他任何东西,我会很容易。

编辑:我尝试了参数化包含/替换,但没有运气。传递的参数被转换为字符串,不能用于其他级别的递归。见https://github.com/ultraq/thymeleaf-layout-dialect/issues/12

非常感谢,

弗兰克

【问题讨论】:

    标签: java spring templates web thymeleaf


    【解决方案1】:

    试试这个:

    为单个菜单项创建一个片段为menuFragment.html

    <html>
        <section layout:fragment="menu">
            <ul>
                <li th:each="menuItem : ${menuItemsList}" th:text="${menuItem.name}">
                    <section layout:include="@{path/to/folder/menuFragment} :: menu" th:with="menuItemsList=${menuItem.children}"></section>
                </li>
            </ul> 
        </section>
    </html>
    

    在你的菜单文件中包含片段

    <section layout:include="@{path/to/folder/menuFragment} :: menu" th:with="menuItemsList=${rootMenuItemAsList}"></section>
    

    rootMenuItemAsList 是包含您的父菜单的列表

    希望对你有帮助

    【讨论】:

    • 此代码不起作用,因为父 li 元素中的 th:text 会覆盖片段中包含的部分。而不是使用 th:text 您必须在 li 元素上使用 th:inline="text" 并在内部部分上方添加实际文本,如下所示 [[${menuItem.name}]]
    【解决方案2】:

    我试过了,在我看来,这条线:

        <li th:each="menuItem : ${menuItemsList}" th:text="${menuItem.name}">
            <section layout:include="@{path/to/folder/menuFragment} :: menu" th:with="menuItemsList=${menuItem.children}"></section>
    

    将覆盖包含(在 li - 标签内),因为 th:text 属性正是这样做的:覆盖 li 块内的内容。

    我让它与以下内容一起使用:

        <li th:each="menuItem : ${menuItemsList}">
            <span  th:text="${menuItem.name}">prototype text...</span>
            <section layout:include="@{path/to/folder/menuFragment} :: menu" th:with="menuItemsList=${menuItem.children}"></section>
        </li>
    

    希望这会有所帮助...

    【讨论】:

      【解决方案3】:

      我主要包括:

      <section th:include="@{categoryFragment} :: category" th:with="maincategories=${categories}"></section>
      

      作为我使用的片段:

      <section th:fragment="category">
          <ul>
              <li th:each="cat : ${maincategories}">
                  <span th:text="${cat.categoryName}">Main Cat</span>
                  <section th:include="@{categoryFragment} :: category" th:with="maincategories=${cat.getChildren()}"></section>
              </li>
          </ul>
      </section>
      

      这对我来说绝对没问题。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-09-22
        • 1970-01-01
        • 2020-09-08
        • 2016-02-16
        • 1970-01-01
        • 2010-09-07
        • 2019-09-09
        • 1970-01-01
        相关资源
        最近更新 更多