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.

Support

Access to collection elements using a numerical index

Solved by Karmalakas View solution

Started by Norbert 3 years ago · 13 replies · 475 views
3 years ago

I have two collections: collection1, collection2.

Based on them, I want to generate an HTML table in which the first column will be the first element of the collection1 array, and the second column will contain the first element of the collection2 array.

So I have the html.twig code:

TWIG
{% set collection1 = page.collection %}
{% set collection2 = page.collection('nabor2') %}
{% set max_length = max(collection1|length, collection2|length) %}

<table class="table">
  {% for i in 0..max_length-1 %}
    <tr>
      <td>{{collection1[i].title}}</td>
      <td>{{collection2[i].title}}</td>
    </tr>
  {% endfor %}
</table>

But it doesn't work.

3 years ago

If you defined doesn’t work more clearly, it would be much easier to help. What happens? Do you get an error? Do you get no output at all?

3 years ago
TWIG
{% for i in 0..max_length-1 %}
    {{debug(collection1[i])}}
{% endfor %}

I get null in the console. However, the collection1 exists and contains many elements.

3 years ago

What do you get for

TWIG
{{debug(i)}}
{{debug(collection1)}}
3 years ago
TXT
0
debugGrav\Common\Page\Collection {#2500 #pages: Grav\Common\Page\Pages {#170 -directory: null #...
1
debugGrav\Common\Page\Collection {#2500 #pages: Grav\Common\Page\Pages {#170 -directory: null #...

and more results of this scheme.

However, if I make a classic loop to display the content, it obviously works:

TWIG
{% for item in collection1 %}
    {{debug(item.title)}}
{% endfor %}

and as a result I get a list of titles.

I understand that a collection object is not an array. However, I don't know how to iteratively access each element, considering that in the view I have to match the first element of collection collection1 with the first element of collection2, etc.

last edited 11/29/23 by Norbert
3 years ago

So you see your collection1 is not an array. You can't just access its elements by index. What's the result of

TWIG
{{debug(collection1.toArray)}}

or is it

TWIG
{{debug(collection1.toArray())}}
{{debug(collection1|toArray)}}

I don't remember the syntax and not at my PC now

3 years ago
TWIG
{{debug(collection1.toArray)}}

result:

TXT

array:23 [
  "/home/norbert/www/czystepowietrze/user/pages/07.inne-programy/03.cieple-mieszkanie/14.pytania-i-odpowiedzi/01.beneficjent-koncowy/01.1-nabor/1" => array:1 [
    "slug" => "1"
  ]
  "/home/norbert/www/czystepowietrze/user/pages/07.inne-programy/03.cieple-mieszkanie/14.pytania-i-odpowiedzi/01.beneficjent-koncowy/01.1-nabor/2" => array:1 [
    "slug" => "2"
  ]
]```
last edited 11/29/23 by Norbert
3 years ago Solution

Do you have title if you use toExtendedArray?
In any case, I see keys are as paths in the converted array, so you'd need to convert it to indexed array. In PHP there's array_values function, but I don't see this in Twig. You could try .toExtendedArray.array_values, but might not work. In such case I'd probably do a bit differently - do two loops to construct your arrays with titles from your collections and then a third loop like you did initially

3 years ago

@q3d:
array:23 [

This looks like a numerically indexed array to me that you could use [n] on.

3 years ago

Wouldn't Twig's slice filter work on the original page collection? Like collection1|slice(n,1)?

3 years ago

@hughbris:
This looks like a numerically indexed array to me

I believe it's not. It's just a count I assume.

JS
[
  "path/1" => ["slug" => "1"],
  "path/2" => ["slug" => "2"],
  // 21 more items here
]

@hughbris:
Wouldn’t Twig’s slice filter work on the original page collection? Like collection1|slice(n,1)?

If slice doesn't work by reference and leaves the actual collection1 intact, then I suppose it might work

3 years ago

{% set collection1 = page.collection.toExtendedArray %}

result:

PHP
array:2 [
  "header" = array:2 [
    "title" = "Lorem ipsum (title)"
    "simplesearch" = array:1 [
      "process" = false
    ]
  ]
  "content" = "Lorem ipsum dolor"
]

and if:

TWIG
{% set keys1 = collection1|keys %}

{{debug(collection1[keys1[0]].header.title)}}

result:

TXT
Lorem ipsum (title)

:)

Thank you Karmalakas!

👍 1
last edited 11/29/23 by Norbert
3 years ago

@Karmalakas:
I believe it’s not. It’s just a count I assume.

I know you have numerical slugs (confusing!) but I think you're right anyway, the formatting is misleading.

👍 1
3 years ago

A collection is not indexed by int, but by string (path of page).

An alternative to Collection::toExtendedArray() could be:

TWIG
{% set collection1 = page.collection %}
{% set paths1 = collection1.toArray|keys %}

{% set collection2 = page.collection('content2') %}
{% set paths2 = collection2.toArray|keys %}

{% set max_length = max(collection1|length, collection2|length) %}

<table class="table">
{% for i in 0..max_length-1 %}
    <tr>
    <td>{{collection1[paths1[i]].title}}</td>
    <td>{{collection2[paths2[i]].title}}</td>
    </tr>
{% endfor %}
</table>

Note: collection1.offsetGet(paths1[i]) could also be used

last edited 11/29/23 by pamtbaau

Suggested topics

Topic Participants Replies Views Activity
Support · by Thomas, 1 week ago
2 53 9 hours ago
Support · by Anna, 3 days ago
2 59 12 hours ago
Support · by Justin Young, 13 hours ago
1 30 13 hours ago
Support · by Duc , 1 week ago
2 65 5 days ago
Support · by Colin Hume, 1 week ago
2 56 5 days ago