1

First, a disclamer -- I am new to Craft CMS.

With that said, I am trying to create a category page whereby the page will show the title, description and image of the sub-categories of the current category. It will do this so long as there are still sub-categories. When there are no longer sub-categories it will then show the entries for that category.

I think I have figured out the code (see below), but I'm having a problem showing the images. On one level the images show fine, but on a lower level the images are being shown in reverse order. I can't figure out why.

Here is the code:

{% set num = 0 %}            
{% set children = category.getChildren() %}
        {% if children|length %}
         {% for child in children %}

        <div id="teaser" class="row">
            <div id="teaser_image" class="columns left small-12 medium-6">


        {% set assets = craft.assets.relatedTo(children).nth(num) %}           
            {% if assets %}
                <img src="{{ assets.url }}" alt="{{ assets.title }}">
            {% endif %}

            </div>     

            <div id="teaser_text" class="columns right small-12 medium-6">
                <h2>{{ child.title }}</h2>
                <p>{{ child.description }}</p>
            </div>
        </div>
        {% set num = num + 1 %}
        {% endfor %}


            {% else %}    
            <div id="teaser" class="row">
                <div id="teaser_image" class="columns left small-12 medium-6">
                        <img src="/images/moses-har-sinai.jpg" alt="">
                </div>

                <div id="teaser_text" class="columns right small-12 medium-6">
                {% set entries = craft.entries.relatedTo(category).level(1) %}
                {% for entry in entries %}
                    <h2>{{ entry.title }}</h2>
                    <p>{{ entry.description }}</p>
                <a class="button small" href="{{ entry.url }}">Learn more</a>
                {% endfor %}

                </div>
            </div>
        {% endif %} 

Now, on the category page: /topics/life/ the images are associated with the proper category.

But on the category page: topics/life/cells, the order is reversed. The first category displays the image for the last category and the last category dispalys the image for the first category. Why is that and what can I do to fix it?

Thanks in advance for any help you can offer.

P.S. Please feel free to let me know if there is a better way to code what I'm trying to do.

  • Maybe show a wireframe of what you expect the output to be? – PKHunter Aug 18 '17 at 16:11
3

It's hard to figure out exactly what your trying to do, but I can see a few potential problems.

  • No need for the 'num' variable, instead use loop.index (or loop.index0 for a zero indexed array); although I don't think you need it at all in this case.
  • nth() is currently returning the 'nth' offset of all assets that are related to all children collectively (thus the strange results). I would guess that you want the asset(s) related to the child category in the current loop. I would also guess that the asset(s) are defined in an assets field in the categories field layout, in which case you can get the asset(s) from the field directly, rather than using .relatedto(child).

Try the following — without understanding your structure entirely, it might at least be a bit closer to what you're looking for.

{% if category.hasDescendants() %}

    {% for childCategory in category.getDescendants() %}

        <div id="teaser" class="row">

            <div id="teaser_image" class="columns left small-12 medium-6">

                {% set asset = childCategory.myAssetsFieldHandle.first %}
                {% if asset %}
                    <img src="{{ asset.url }}" alt="{{ asset.title }}">
                {% endif %}

            </div>     

            <div id="teaser_text" class="columns right small-12 medium-6">
                <h2>{{ childCategory.title }}</h2>
                <p>{{ childCategory.description }}</p>
            </div>

        </div>

    {% endfor %}

{% endif %}

<div id="teaser" class="row">

    <div id="teaser_image" class="columns left small-12 medium-6">
        <img src="/images/moses-har-sinai.jpg" alt="">
    </div>

    <div id="teaser_text" class="columns right small-12 medium-6">

        {% set entries = craft.entries.relatedTo(category) %}
        {% for entry in entries %}
            <h2>{{ entry.title }}</h2>
            <p>{{ entry.description }}</p>
            <a class="button small" href="{{ entry.url }}">Learn more</a>
        {% endfor %}

    </div>

</div>

Note: this is assuming that you want to show the subcategories and then the entries related to the main category. If not, then I misinterpreted your question and you will want to reconfigure this a bit, but the principles should be the same.

  • 1
    That did it - thanks. Now, just to make sure I understand why it worked, what exactly is the 'first' command that you chained to the assets field handle getting the first off? If I understand correctly, it is getting the first image of the particular category that we are looping through right now -- is that right? – Moshe Feb 16 '15 at 9:24
  • Asset fields always return an array of assets, even if only one is defined. Using 'first' will grab the first image in the array; otherwise you would need to loop through the returned assets. – Douglas McDonald Feb 16 '15 at 15:43
  • 1
    By the way, It's also probably better to use 'hasDescendants()' and 'getDescendants()' (or just 'descendants') as some uses of getChildren are being deprecated. – Douglas McDonald Feb 16 '15 at 16:00
  • Thanks. I'll look into those options and update the code. – Moshe Feb 18 '15 at 21:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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