Adding a collection module

I need a module for a modular page, that lists subpages of a specific folder like blog items are displayed on the blog page.

I read about collections and managed to create an unordered list with the respective page titles.

I read about theme development a bit and understood some basics. This led me to the idea to copy blog.html.twig into the modular folder. Aside from having unexpected visual side effects, specifying items: 'blog' or items: 'details' does not deliver the desired result.

I just want to have “nice previews” of the pages like they are on the blog page. And those pages reside in several subfolders. The goal ist to have a kind of summary or overview module—if they were taxonomy-aware, it would be even better, as I could keep my detail pages in one folder. :wink:

Well, to cut a long story short: What did I miss? What could I try in order to get my module working?

Does nobody have an idea how to realize this?
Or did I post this into the wrong sub forum?

@Vince42, To get a collection of blog-items based on their taxonomy, try:

  • Add collection to frontmatter of module:
           '@taxonomy.tag': [photography]
  • In the template of the module, add:
      {% for item in page.collection %} 
        <li>{{ item.title }}</li>
      {% endfor %}

I already achieved this successfully a while ago. I am struggling with using the partial blog item (three or four columns with nicely rendered picture and the summary below).

Therefore I thought about reducing the blog page twig to a minimal viable collection and using the blog item partial—but I miserably fail on reducing and reusing as I am new to themes and just started to get my head around this.

My “pages” module is stolen from blog.html.twig and stored in modular/pages.html.twig and reads as follows:

{% set grid_size = theme_var('grid-size') %}
{% set collection = page.collection() %}

{% block stylesheets %}
    {% do assets.addCss('theme://css/bricklayer.css') %}
{% endblock %}

{% block javascripts %}
    {% do assets.add('theme://js/bricklayer.min.js') %}
    {% do assets.add('theme://js/scopedQuerySelectorShim.min.js') %}
{% endblock %}

{% block body %}
    <section id="body-wrapper" class="section blog-listing">
        <section class="container {{ grid_size }}">
        {% embed 'partials/layout.html.twig' with {page} %}
            {% block item %}
                <div class="bricklayer">
                {% for child in collection %}
                    {% include 'partials/page-summary.html.twig' with {child} %}
                {% endfor %}
            {% endblock %}
        {% endembed %}
        var bricklayer = new Bricklayer(document.querySelector('.bricklayer'))
{% endblock %}

The partial “page summary” ist stolen from blog-item.html.twig and stored in partials/page-summary.html.twig and reads:

<div class="card">
    {% set image =|first %}
    {% if image %}
    <div class="card-image">
        <a href="{{ page.url }}">{{ image.cropZoom(200,100).html|raw }}</a>
    {% endif %}
    <div class="card-header">
        <div class="card-title">
            {% include 'partials/blog/title.html.twig' with {title_level: 'h5'} %}
    <div class="card-body">
        {% if page.summary != page.content %}
            {{ page.summary|raw }}
        {% else %}
            {{ page.content|raw }}
        {% endif %}

I have a folder named details, where I want to store a multitude of pages. A group of pages has the same taxonomy category, for example MyCategory.

The module in my modular page has the following frontmatter (the weird empty spaces are created by Grav, the original markup looked differently):

    markdown: true
    twig: true
body_classes: modular
            '@page.children': /details
                - MyCategory
        by: date
        dir: asc
    limit: 8
    pagination: true

Clearing cache, loading page: I almost receive what I want (at least visually):

Reloading the page without changing anything (!):

Surprise, surprise - no idea, why that happens.

Aside from that weird behaviour, the selection of pages does not reflect the specified category and the page collection, which works with twig in the module, does not work, when I move the code to the module file.

Ya, well, typical newbie problems, if you are new to a concept and don’t understand what to fiddle in where. This was just an update.


Ok, so the title of the post doesn’t really reflect the issue. Or does it? If not, please update the title.

Anyway… You mention two issues in your last reply…

  • the selection of pages does not reflect the specified category
    You haven’t mentioned what the selection does reflect, so, based on the images you’re showing, I’m guessing it repeatedly shows the content of the modular page and not the pages in the collection.

    In template pages.html.twig you use the following to include the summary template:

    {% include 'partials/page-summary.html.twig' with {child} %}

    Variable child, which refers to a page in the collection, is being passed to the summary template.
    However, in template page_summary.html.twig you are using variable page, which is the original page variable referring the modular page.
    You should be using child inside page-summary.html.twig.

    Tip: Use {{ dump(variable) }} in Twig to ‘dump’ the contents of a variable. This could eg. be the collection, or the page variable. Use clockwork to check the dump in the browser.

  • Surprise, surprise - no idea, why that happens.
    This happens due to the nature of caching of modular pages. Once the templates of the module has been parsed, a ‘data’ file is being generated with the generated HTML. Twig will not run again. Because of that, the bricklayer library will not be loaded when refreshing the page. Hence a vertical list of summaries.

    Tip: Always check the console of the browser to check if there are any errors. In this case an error is being thrown by Bricklayer telling the library isn’t being loaded.

    NB. In ‘normal’ pages, only the parsed Twig will be cached and will still run on every request.


    • Add never_cache_twig: true (or cache_enable: false) to the frontmatter of the ‘pages’ module.
    • Or move the loading of the bricklayer assets into the template of the modular.
      Which might not always be desirable when a modular does not contain the ‘pages’ module.

First of all: Thank you, that you are always taking the time to help newbies like me to understand Grav a little bit better! I highly appreciate it!

Unfortunately I do not know how to edit the title, but the long form would be “Adding a collection module that lists pages with a certain taxonomy category from a specified subfolder like blog items are listed on the blog page”. I hope, that this clarifies my goal. Thank you for pointing this out.

I have created four pages in my details folder, two of them having a category, two of them are without any taxonomy. The first thing I expected was, that only two and not four pages were caught in the collection.

Secondly I expected that the child page were rendered, but instead the content of the module (which is supposed to function as introductary text) is rendered in all four calls. Your explanation clarified this behaviour, thank you! I changed the variable from child to page and this fixed it.

The first phonomenon remains though: The taxonomy category is ignored and all four sub pages are rendered.

I still wonder, why the YAML is reformatted and strangely indented, once I hit save. The original was

        - '@page.children': /details
        - '@taxonomy.category': [MyCategory]

and this was turned into

            '@page.children': /details
                - MyCategory

Might this be the problem, why the proper selection of the collection fails?
And is there a way to hinder Grav to reformat the frontmatter or does this happen for a good reason that I simply do not understand? At least it looks ugly … :wink:

Awesome, it works. I wish I knew so much about the inner mechanisms as you do. Thank you again so much!

May I ask two additional questions that just came to my mind?

I did not understand the whole bricklayer thing. Is there an easy way to control the amount of bricks (I guess those are the summary cards that are displayed) in a row? I would like to have, for example, max 4 bricks per row.

And is there a way to have this parameter editable in the web frontend page editor for the average user like features are managed in the feature module?

The first phonomenon remains though: The taxonomy category is ignored and all four sub pages are rendered.

Have a look at the docs on Collections and especially about Complex Collections. Is says:

You can also provide multiple complex collection definitions and the resulting collection will be the sum of all the pages found from each of the collection definitions.

(Emphasis mine)

Each items line is evaluated separately and added to the result.

In your case: Give me all pages from folder /details plus all pages with category “MyCategory”.

Since all pages with a category are inside the /details folder, you won’t see a difference using the category. If there were two separate folders like /details and /blog where the blog items have a category, then there would be a difference.

I still wonder, why the YAML is reformatted and strangely indented, once I hit save.

I don’t know, but they seem both to be valid Yaml and have no different meaning.

May I ask two additional questions that just came to my mind?

Sure, you may ask as many questions as you like on the forum, but… Not in the same post.

Please mark this question as solved and create a new post with a proper title.

2 posts were split to a new topic: Collection with multiple item constraints