Pregunta

I would like to render HTML menu using ul/li list. I've got this class structure:

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;
    }
} 

As you can see it's typical tree structure, in which one root element contains reference to its children and they have reference to theirs and so on.

Now I would love to render structure like this:

<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>

How can I do that with thymeleaf? I'm easy if I have to use other technologies like Tiles, Layout or anything else.

EDIT: I tried parameterized include/replace but with no luck. Parameters passed through are converted to String and can't be used for another level of recursion. See https://github.com/ultraq/thymeleaf-layout-dialect/issues/12

Thank you very much,

Frank

¿Fue útil?

Solución

Try this:

Create a fragment for single menu item as 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>

Include the fragment in your menu file as

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

rootMenuItemAsList is a list with your parent menu

Hope this help will you

Otros consejos

I tried this and it seems to me that the line:

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

will overwrite the include (inside the li - tag) because the th:text attribute does exactly that: overwrite the content inside the li block.

I got this to work with the following:

    <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>

Hope this helps...

In my main I include:

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

and as Fragment i use:

<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>

This works absolutly fine for me.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top