3

I have a category listing template where I'm having trouble passing in some variables.

top of the template I have this snippet where I'll set the channel and category field name based on the segment

{% set segment = craft.request.segment(1) %}

{# set channel based on segment_1 #}
{% if segment == "business-intel" %}
    {% set channelName = "businessIntel" %}
    {% set categoryName = "businessIntelCategories" %}
{% elseif segment == "foo" %}
    {# do nothing #}
{% endif %}
{# end set channel #}

Then further down the template I have this:

{% include ('_includes/cat_sub_with_article') with { 'categoryName' : categoryName } %}

And then the included template looks like this:

 {% for category, catEntries in entries | group('categoryName.first().title') %}
    <h2>{{ category }}</h2>


    {% set featuredThumb = {
        mode: 'crop',
        width: 370,
        height: 168,
        quality: 90,
        position: 'top-center'
      } %}

    <div class="article-cards">
        {% for entry in catEntries %}
        <div class="article-card__wrapper">
            <a href="{{ entry.url }}" class="article-card">

                {% set image = entry.featuredImage.first() %}

                <span class="article-card__image">
                    <img src="{{ image.url(featuredThumb) }}" />
                </span>
                <span class="article-card__text">
                    <span class="article-card__category">{{ entry.postDate.format('M d, Y') }}</span>
                    <h3 class="article-card__title">{{ entry.title }}</h3>
                    <p>{{ entry.featuredSummary }}</p>
                    <p><span class="link--green" href="{{ entry.url }}">Learn More</span></p>
                </span>
            </a>
        </div>
        {% endfor %}
    </div><!-- /.article-cards -->
 {% endfor %}

If I hardcode the category field name into line 1 of the above block everything works. However if I try to use the passed varialbe. I get this error, which I don't know how to fix:

Craft\EntryModel and its behaviors do not have a method or closure named "categoryName".

1 Answer 1

3

You set the variable that your are passing in to your include to a string. And in your include you try to access it like an object.

The variable which you’re passing in to your include is set to a string 'businessIntelCategories'. And in your include you try access a object property dynamically using that string which doesn’t work.

Use this code instead.

{% set entriesGrouped = entries|group('{ object[categoryName].first().title }') %}

Here’s an attempt to explain the syntax.

First you should have a look at the Craft documentation for Dynamic Entry Titles. You see that you can dynamically generate titles with a normal Twig template {{ object.property }} or a special shortcut syntax {property}.

The group filter uses the same internal functionality to render the string that you pass in as a filter argument group('my twig template string'). The syntax has to be a bit different though, because group already adds one pair of curly braces for you.

So usually you echo the title property like so

{{ object.title }}

and in the context of the group filter you can do both of the following.

{% set entriesGrouped = entries|group('title') %}

{% set entriesGrouped = entries|group('{ object.title }') %}

The first syntax, which uses the shortcut syntax, is documented and fine for most cases. But you can’t use it if you need to do something a bit more advanced, like using a ternary operator or in your case access the object object differently.

So to wrap this up, the syntax for group('{ object[categoryName].first().title }') is confusing. But what it does is to render the following Twig code for each element of your array of entries (each entry is passed in as the variable object).

{{ object[categoryName].first().title }}

If you don’t like the object['propertyName'] syntax, you can use the attribute function instead.

{{ attribute(object, categoryName).first().title }}
1
  • That worked but I don't understand why.
    – CreateSean
    Mar 7, 2017 at 14:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.