Order collection by 'custom' or 'manual' in Twig

Hi folks,

to create and show a page collection via

{% set options = { items: {'@page.children': '/myfolder'}, 'order': {'by': 'title', 'dir': 'desc'} } %}
{% set my_collection = page.collection(options) %}
<ul>
  {% for p in my_collection %}
    <li>{{ p.title|e }}</li>
  {% endfor %}
</ul>

within a myfile.html.twig works fine. The structure of folders and files (and titles) is this:

04.myfolder ()
–01.subfolder_a (default.md - title ‘lorem’)
–02.subfolder_b (default.md - title ‘ipsum’)
–03.subfolder_c (default.md - title ‘dolor’)

I’d like to know how I can affect the ordering by using manual or custom. After one and a half hour of searching the learning section ( Page Collections | Grav Documentation (getgrav.org)) and several forum entries I ended up with no success at all. I tried this e.g.:

{% set options = { items: {'@page.children': '/footer'}, 'order': {'by': 'custom', 'custom': '01.subfolder_a|03.subfolder_c|02.subfolder_b'} } %}
{% set my_collection = page.collection(options) %}

with and without the numbers, using , instead of | and many other firings into the blue containing added frontmatter information in variable ways.

So, any help is appreciated. Thank you!

Greetings,

Markus

@Markus, You’re close, but ‘custom’ expects an array like in the yaml example in the docs…

Try:

{% set options = { 
    items: {
        '@page.children': '/footer'
        }, 
    order: {
        custom: [
            'subfolder_a', 
            'subfolder_c', 
            'subfolder_b',
            ]
        }
    } 
%}

Thank you @paamtbau. Yes, close… your code works - but I am wondering, that your code is working although there is a comma after the last element subfolder_b … this often throws an error.

Is there a difference between custom and manual? I just replaced custom

{% set options = { items: {'@page.children': '/footer'}, order: {custom: ['subfolder_a','subfolder_c','subfolder_b']} } %}

with manual

{% set options = { items: {'@page.children': '/footer'}, order: {manual: ['subfolder_a','subfolder_c','subfolder_b']} } %}

but this does not work and I have not found anything yet about order_manual, like it is said in the learning-section. Perhaps I have overlooked something?

Greetings,

Markus

@Markus, The order_manual refers to the variable in the frontmatter of the page:

---
content:
    items: self@.children

order_manual:
    - subfolder_a
    - subfolder_c
    - subfolder_b
---

From the docs:

manual The order is based on the order_manual variable
custom The order is based on the content.order.custom variable

Hi @Paamtbau,

maybe I am dumb, but the docs are - in my opinion - not sufficient enough to get the point how to use that. It might be as easy as cooking water, but I am missing an example.

So, my case is the following: I would like to show and order several links within the footer to some pages. The classic imprint, data protection, contact and so on. These pages are located within the folder “footer”. I collect them, loop thru them and they appear in frontend - or not.

To understand all of the possibilities of grav, I try every option given.

The simple ones are really simple to understand, all fine, like this one:
{% set options = { items: {'@page.children': '/footer'}, order: {by: 'date', dir: 'asc'}} %}

Even ordering by header.x was no problem:
{% set options = { items: {'@page.children': '/footer'}, order: {by: 'header .footer_id', dir: 'asc'} } %}

Using custom works too, thanks to your input. Using manual, for me, seems to be a possibility to order those pages within the collection depending on the frontmatter on each page which is currently shown.

For example, if I configure this in frontmatter of the page “home”

order_manual:
  - imprint
  - dataprotection
  - contact

I assumed, that the order within the footer would be imprint, dataprotection, contact, when showing the page “home”.

And if I configure this in frontmatter of the page “test”

order_manual:
  - contact
  - dataprotection
  - imprint

I assumed that the order within the footer would be contact, dataprotection, imprint when showing the page “test”.

Based on your comment, I declare this within footer.html.twig
{% set options = { items: {'self@.children': '/'}, order: {by: 'header .order_manual'} } %}
or
{% set options = { items: {'self@.children': ''}, order: {by: 'header .order_manual'} } %}
or
{% set options = { items: {'self@.children': '/'}, order: {by: 'manual'} } %}
or
{% set options = { items: {'self@.children': '/footer'}, order: {'manual': ''} } %}

to be considered by
{% set my_collection = page.collection(options) %}

Nothing works and I do not find any example of using order_manual. The sole and general description “this depends on that” of the docs might be sufficient enough for those who are familiar with grav - but, for me, I am sorry for missing a “living example”.

So, may some wisdom fall down on me… :wink:

Greetings,

Markus

@Markus, Here is an example for using ‘manual’:

Folder structure /pages

user/pages
├── 01.home
├── 02.typography
└── footer
    ├── default.md
    ├── x
    │   └── default.md
    ├── y
    │   └── default.md
    └── z
        └── default.md

/footer/default.md

---
order_manual:
    - z
    - y
    - x
---

/user/themes/quark/templates/default.html.twig

{% set options = { 
    items: {
        '@page.children': '/footer'
        }, 
    }
%}
{% set my_collection = page.collection(options) %}

The resulting ordering will be according the pages listed in order_manual in page /footer/default.md.

Notes:

  • Variable order_manual must be defined in the frontmatter of the page at hand. In this case, there must be a page defined in the root of /footer, with the proper frontmatter.
  • The manual ordering cannot be defined in the collection definition.
  • There should be no ‘order’ defined in the collections definition in Twig. Not even order: { by: 'manual '}
  • If no order is defined, the value of order_manual will be taken as default.

Yes, above notes may seem ‘unexpected’, but that might be because I have difficulty understanding the use-case of manual and its added value over custom.

I’ve created an issue to ask for a proper use-case for this option and asked for some samples. Maybe that will clear the ‘unexpectedness’.

Hi @Paamtbau,
thanks a lot for your comment! That was exactly what I needed and ordering by manual/order_manual works fine. :grinning:

the use-case of manual and its added value over custom .

I might have the solution for that or at least one advantage. :slight_smile:

When you set the order for custom within the footer.html.twig, it is hardcoded. If a folder is renamed, the ordering should not work anymore and you can not alter the file via the admin panel. Using manual avoids this problem, because the information about the order is not contained within the twig-file and reachable via admin-panel.

So, again thanks for your support and for posting an issue about the use of manual.

See ya,

Markus

@Markus, Yes, I got the ‘hardcoded’ and Admin part, but if that is all there is, it could also be achieved, even simpler, as follows:

  • Same folder structure as above.
  • /pages/footer/default.md
    ---
    content:
        items: 'self@.children'
        order:
            custom:
                - y
                - z
                - x
    ---
    
  • Twig: /user/themes/quark/templates/default.html.twig
    {% for child in pages.find('/footer').collection %}
        {{ child.title }}
    {% endfor %}
    

There is now even less hardcoded in Twig because everything is defined in the page’s frontmatter.

@Markus, Have had a discussion with the dev team: manual should not be used.

[…], after some investigation, it looks like the order_manual is leftover from backward compatibility and should never be used. It just messes up collections, especially if you want to use multiple collections.

Hi @pamtbaau,

thank you for your further investigations. Well, it seems there has to be an additional comment within the learning-section then… - Ah, wanted to paste a link in here and recognizing, there is an added “deprecated”…

Thumbs up!

Markus