Skip to content
Grav 2.0 is officially stable. Read the announcement →

Community guidelines

Please keep discussions civil and on-topic. Repeated violations may lead to a temporary ban.

General

Complex collections depending on Frontmatter headers and it's value?

Started by Alexander Kim 8 years ago · 14 replies · 1230 views
8 years ago

Include partial view with a complex collection:

TWIG
{% include 'partials/article-main.html.twig' with {'page': #here goes condition} %}

How can i choose all pages, that has a field named main_article in the headers/Frontmatter set to true?

Or even without that "with" part directly in a TWIG file:

TWIG
{% set options = { items: {'@root': #someCondition here} } %}
{% set main_collection = page.collection(options) %}
8 years ago

Well, it's Easter. The Grav experts are probably on vacation, enjoying well deserved time outside in the nature with their families, friends and/or significant others. It's only the struggling newbies like me who still have to sit in front of their computers, learning how to use Grav.

If I understand you correctly (and I'm not certain I do), you probably want something like this:

TWIG
  {% for p in pages.children.visible if p != page %}
    {% if p.header.main_article %}
      {# Do stuff. #}
    {% endif %}
  {% endfor %}
👍 1
8 years ago

Thank you for your answer, i think it's trivial task, that everyone would want to do, it's just like u're doing a SELECT page WHERE main_article = true query from database , i just want to get all pages with that field set to true only, then use it in collection:

TWIG
{% set options = { #here we filter all pages with header.field set to true } %}

# then we're using this as collection
{% set main_collection = page.collection(options) %}

Won't your example make a huge performance hit, because it will iterate over all pages, if i want just one with that field set to true.

last edited 03/31/18 by Alexander Kim
8 years ago

@heihachi88:
Won’t your example make a huge performance hit?

I wouldn't know. I'm really quite new to Grav. I suppose, once Easter is over and the forum becomes more vivid, somebody with more experience might double check this.

That being said: I got that approach from reading the Twig templates of the "Antimatter" theme where looping over pages.children.visible is used in the navigation partial. Also, my expectation would be that a) performance issues would come up only with really, really huge sites. (It's just looping through an PHP array and checking a value.) and that b) caching takes care of that anyways.

I don't quite understand, why you need to construct a collection in Twig. My (possibly wrong) understanding is that collections are just a way to define a set of pages in a page's markdown file. In my (again: possibly wrong) understanding, they're not something you'd define in a Twig file.

However, in that vein, the documentation mentions taxonomy collections: https://learn.getgrav.org/content/collections#taxonomy-collections

So if it's okay for you to define your main_article pages by adding a tag instead of a field in the frontmatter, you might just use something like (untested):

YAML
content:
   items:
      '@taxonomy.tag': main_article
last edited 03/31/18 by Oliver Scholz
8 years ago

I'll explain the logic behind it. In admin section i've added field of type "toggle" (using blueprints) with options - yes or no. When admin toggles this to yes, then this page is going to be shown on the front page as preview: image and title. You think, that using taxonomies would fill my needs?

I think using taxonomies would be inconvenient for site administrator, because he would have to choose that tag vs just toggling yes/no button.

last edited 03/31/18 by Alexander Kim
8 years ago

I think that's a matter of taste. Using a tag like 'featured' is perfectly reasonable if you think of "being featured on the front page" as "this is an additional property of that article".

I had a very similar case: pages to be featured with images in a side bar. I tried the taxonomy approach first. But then I thought: having a toggle, like you, is better for this particular site and this particular end user. I ended up using the approach I first posted (from the Antimatter theme), i. e. iterating over pages.children.visible. I think that's perfectly reasonable and straight forward.

Reading the documentation some more, it seems like creating collections from Twig or even PHP is a thing. From the looks of it, it seems useful when using complex taxonomies, sorting orders etc. However, reading both the documentation and <site name>/system/src/Grav/Common/Page/Collection.php, I see nothing to filter collections based on a flag in the frontmatter.

(Again: I'm new to Grav, so I might be wrong with everything.)

8 years ago

Documentation is clearly missing information about filtering collections. I guess, grav team is not implemented this kind of things yet.

So you've ended using taxonomies or like this:

TWIG
{% set options = { items: '@root.descendants', 'order': {'by': 'date', 'dir': 'desc'}, 'pagination': false } %}
{% set main_collection = page.collection(options) %}

{% for p in main_collection|slice(0, 1) if p.header.main_article %}
    {{ dump(p) }}
    <article class="main-news">
        <a href="/" class="d-block mb-3">
            <img src="{{ p.header.image }}" alt="..." class="img-responsive w-100 rounded">
        </a>

        <a href="/">
            <h4>{{ p.title }}</h4>
        </a>
    </article>
{% endfor %}

A few things bothering me using this approach:

  1. Iterates over all pages;
  2. If i set 'limit': 1 in ordering, then it wouldn't work, because it's limited to one page and if it's page doesn't have that field in a header, then nothing would be shown;

By the way:

@Utis:
{% for p in pages.children.visible if p != page %}

What does mean if p != page, it means if it's not a page object? Then what else it could be, except the page ? 😃, maybe i'm misunderstanding something.


In my understanding - collections is like an Eloquent in Laravel (DB Query builder), is it wrong?

last edited 04/01/18 by Alexander Kim
8 years ago

Ah, I understand now that there's only ever to be one page with that flag. Yeah, it seems like it's not possible to break from a for loop in Twig.

@heihachi88:
{% for p in pages.children.visible if p != page %}

What does mean if p != page, it means if it’s not a page object?

page is the current page. It's to avoid having a page featuring itself; the way I understood you at first, I thought that would be useful.

8 years ago

@Utis:
Ah, I understand now that there’s only ever to be one page with that flag. Yeah, it seems like it’s not possible to break from a for loop in Twig.

Only one will be shown (in frontend - to the user), but there could hundreds of them with main_article set to true.

8 years ago

@Utis:
{% for p in pages.children.visible if p != page %}
{% if p.header.main_article %}
{# Do stuff. #}
{% endif %}
{% endfor %}

How do you order items using this method? Without collections is impossible to order pages, as i know.

8 years ago

The sort order is the same as it appears in the "Pages" section of the admin panel; which means: users can order it manually. This is what I needed for my sidebar.

I learned something about collections through our discussion; in your case, I'd use a collection now, too.

8 years ago

Grav dev's should take care of that issue with filtering collections, hope to see it live very soon.

8 years ago

I've faced another issues - it's not possible to limit number of articles, while using Twig's for... Dev's are you there?

8 years ago

If you want to limit your range of articles, this should be of help to you I think :) In combination with this you could turn the current article id (if there is one) into a number that scopes your from .. to .. range :) Hope it helps!
https://twig.symfony.com/doc/2.x/functions/range.html

Suggested topics

Topic Participants Replies Views Activity
General · by Jerry Hunt, 4 days ago
2 80 9 hours ago
General · by pamtbaau, 14 hours ago
1 51 13 hours ago
General · by Andy Miller, 1 day ago
0 44 1 day ago
General · by Marcel, 12 months ago
6 346 5 days ago
General · by Duc , 5 days ago
3 40 5 days ago