How to iterate and display nested categories or content structures in a template?

In website operations, we often need to build complex and well-structured content, such as multi-level classification navigation, product tree structure, or nested display of related articles under categories.AnQiCMS (AnQiCMS) makes it simple and efficient to traverse and display these nested structures in templates, thanks to its flexible template engine and rich tag features.

The template system of AnQi CMS uses a syntax similar to Django, which means you will mainly{{变量}}output data, and through{% 标签 %}Execute logic control, such as conditional judgment and loop traversal. Deep understanding{% for ... in ... %}Loop tags and the parameters and return structures of various data tags are the key to realizing complex nested display.

Understand the loop and judgment in the template.

In AnqiCMS template,{% for item in items %}the structure is the core of traversing list data. Each loop,itemVariables will point to an element in the list, you can access its internal data byitem.属性名. For example, when iterating over a categorized list,itemMay represent a category object, you can accessitem.Title(Category title),item.Link(Category link) etc.

At the same time,{% if 条件 %}Tags allow you to conditionally render based on the specific state of data, which is particularly useful when dealing with nested structures, such as determining if a category has subcategories. If the traversed list may be empty, you can also use{% empty %}Provide an alternative display for cases without content.

Traverse and display nested category structure.

AnQi CMS providescategoryListTag to get category data. The key to displaying nested categories lies in cleverly utilizingparentIdparameters and the category object itself.HasChildrenproperties.

Firstly, you can get the top-level category list:

{% categoryList categories with moduleId="1" parentId="0" %}
    {# 一级分类列表 #}
    <ul>
        {% for category in categories %}
            <li>
                <a href="{{ category.Link }}">{{ category.Title }}</a>
                {# 判断当前分类是否有子分类 #}
                {% if category.HasChildren %}
                    {# 如果有子分类,则再次调用 categoryList 标签,并将其 parentId 设置为当前分类的ID #}
                    <ul>
                        {% categoryList subCategories with parentId=category.Id %}
                            {% for subCategory in subCategories %}
                                <li><a href="{{ subCategory.Link }}">{{ subCategory.Title }}</a></li>
                            {% endfor %}
                        {% endcategoryList %}
                    </ul>
                {% endif %}
            </li>
        {% endfor %}
    </ul>
{% endcategoryList %}

This code demonstrates how to recursively traverse two levels of classification. For deeper nesting, you can check within the loop again in the same pattern.subCategories.subCategory.HasChildrenand callcategoryList.

Display related content in nested categories

The website structure often needs to associate categories with specific content (such as articles, products). In AnqiCMS, you cancategoryListTags witharchiveListTags are used together, displaying both categories and some of their contents simultaneously.

{% categoryList categories with moduleId="1" parentId="0" %}
    {# 遍历一级分类 #}
    {% for category in categories %}
        <div class="category-block">
            <h3><a href="{{ category.Link }}">{{ category.Title }}</a></h3>
            <ul>
                {# 在每个分类下,获取其关联的文章列表 #}
                {% archiveList articles with type="list" categoryId=category.Id limit="5" %}
                    {% for article in articles %}
                        <li>
                            <a href="{{ article.Link }}">{{ article.Title }}</a>
                            <span>{{ stampToDate(article.CreatedTime, "2006-01-02") }}</span>
                        </li>
                    {% empty %}
                        <li>该分类暂无文章。</li>
                    {% endfor %}
                {% endarchiveList %}
            </ul>
        </div>
    {% endfor %}
{% endcategoryList %}

Here,archiveListTags go throughcategoryId=category.IdParameters, precisely obtained the articles under the current loop category. You can adjust it according to your needs.limitParameters to control the number of articles displayed.

Use the navigation list to implement multi-level menus.

Except for manually constructing the classification hierarchy, the Anqi CMS ofnavListLabels are an ideal choice for building multi-level navigation menus. This tag directly returns a pre-processed data structure with nested relationships, greatly simplifying the development of multi-level menus.

The multi-level navigation configured on the backend can be directly called like this in the template:

{% navList mainNavs %}
    <ul class="main-menu">
        {% for nav in mainNavs %}
            <li {% if nav.IsCurrent %}class="active"{% endif %}>
                <a href="{{ nav.Link }}">{{ nav.Title }}</a>
                {# 判断当前导航项是否有子导航 #}
                {% if nav.NavList %}
                    <ul class="sub-menu">
                        {% for subNav in nav.NavList %}
                            <li {% if subNav.IsCurrent %}class="active"{% endif %}>
                                <a href="{{ subNav.Link }}">{{ subNav.Title }}</a>
                                {# 还可以继续检查 subNav.NavList 实现更深层次的嵌套 #}
                            </li>
                        {% endfor %}
                    </ul>
                {% endif %}
            </li>
        {% endfor %}
    </ul>
{% endnavList %}

navListReturnednavThe object hasNavListProperties can be used directly to iterate over its child navigation items, making the construction of multi-level menus very intuitive.

Furthermore, you can even add items under these navigation items based on their associatedPageIdIf the link of the navigation item is to a category or a single page, call it againarchiveListorcategoryListto display related content:

{% navList mainNavs %}
    <ul class="main-menu">
        {% for nav in mainNavs %}
            <li>
                <a href="{{ nav.Link }}">{{ nav.Title }}</a>
                {% if nav.NavList %}
                    <ul class="sub-menu">
                        {% for subNav in nav.NavList %}
                            <li>
                                <a href="{{ subNav.Link }}">{{ subNav.Title }}</a>
                                {# 如果子导航关联的是一个分类,显示该分类下的文章 #}
                                {% if subNav.PageId > 0 %}
                                    {% archiveList articles with type="list" categoryId=subNav.PageId limit="3" %}
                                        {% if articles %}
                                            <div class="articles-in-menu">
                                                {% for article in articles %}
                                                    <p><a href="{{ article.Link }}">{{ article.Title }}</a></p>
                                                {% endfor %}
                                            </div>
                                        {% endif %}
                                    {% endarchiveList %}
                                {% endif %}
                            </li>
                        {% endfor %}
                    </ul>
                {% endif %}
            </li>
        {% endfor %}
    </ul>
{% endnavList %}

This example cleverly combines navigation, classification, and content to build a highly dynamic and rich information display.

Nested application of custom fields in the model

In the AnQi CMS, content models and categories both support custom fields.These custom fields can also include more complex, nested data structures, such as image galleries (Images).You can implement their display by iterating over these fields.

If the document detail page has a field namedImageswith a custom image set:

{% archiveDetail archiveImages with name="Images" %}
    <div class="product-gallery">
        {% for img in archiveImages %}
            <img src="{{ img }}" alt="产品图片">
        {% endfor %}
    </div>
{% endarchiveDetail %}

Similarly, if you define categories or document models in the background,ExtraParameters (for example, additional information containing multiple key-value pairs), can bearchiveParamsorcategoryDetailtraversed after retrieval:

{% archiveParams params %}
    <div class="extra-info">
        {% for item in params %}
            <p><strong>{{ item.Name }}:</strong> {{ item.Value }}</p>
        {% endfor %}
    </div>
{% endarchiveParams %}

This allows you to flexibly display custom data, whether it's simple text or complex image collections.

Summary

The template engine of AnQi CMS provides powerful flexibility to handle various nested structures. By proficiently utilizing{% for %}/{% if %}tags, as well ascategoryList/archiveListand `navList`