Take the 2-minute tour ×
Craft CMS Stack Exchange is a question and answer site for administrators, end users, developers and designers for Craft CMS. It's 100% free, no registration required.

I have a type of content that i use on the homepage of a site I am building, the code is shown here:

<ul>
    {% for point in entry.keyPoints %}
        <li>
            <div class="a-ico">
                <i class="fa fa-{{ point.icon }}"></i>
            </div>
            <div class="a-info">
                <h4>{{ point.heading }}</h4>
                {{ point.text }}
            </div>
        </li>
    {% endfor %}
</ul>

This does exactly what i want it to do. It opens a UL and then loops through the different items which are LI's and output accordingly.

I want to use this same type of content on inner pages however as a matrix block TYPE rather than being the only type of content like on the homepage in the above example.

The problem then is that the FOR loop starts before i even know if this is the type of content i am dealing with so I can't appropriately wrap this type in a UL.

I can solve this by checking if it is the FIRST of TYPE and LAST of TYPE and outputting the opening and closing UL tags that way.

I then run into another problem that the first and last of this type are not necessarily adjacent to each other. If that is the case then all the other content TYPEs in the matrix between the FIRST and LAST of this TYPE will be inside of the UL as well.

My question then is how can i determine if the other matrix blocks that are immediately adjacent to this TYPE are of the same TYPE and if they are don't close the UL and if they are NOT then close the UL.

My code to determine what type is is just a simple FOR loop and then inside it a series of conditionals checking the TYPE and then outputting the appropriate content accordingly.

share|improve this question

2 Answers 2

up vote 2 down vote accepted

Fun question! :)

You can use getNext() and getPrev() Methods on the MatrixBlockModel documentation page.

{% for point in entry.keyPoints %}

    {# if this is the "typeToWrap" block type #}
    {% if point.type == 'typeToWrap' %}

        {# if there is a previous point to check #}
        {% if point.getPrev() %}

            {# if the previous point wasn't the "typeToWrap" type start a ul #}
            {% if point.getPrev().type != 'typeToWrap' %}
                <ul>
            {% endif %}

        {# if there isn't a previous point start a ul #}
        {% else %}
            <ul>
        {% endif %}

    {% endif %}

    {# output point #}

    {# if this is the "typeToWrap" block type #}
    {% if point.type == 'typeToWrap' %}

        {# if there is a next point to check #}
        {% if point.getNext() %}

            {# if the next point isn't the "typeToWrap" type end a ul #}
            {% if point.getNext().type != 'typeToWrap' %}
                </ul>
            {% endif %}

        {# if there isn't another point end a ul #}
        {% else %}
            </ul>
        {% endif %}

    {% endif %}

{% endfor %}
share|improve this answer
    
Nice work @Simon! Very detailed answer. These are both good answers IMHO... Yours is more specific to the OP's exact situation, whereas mine is more general purpose. –  Lindsey D Aug 9 at 23:42
    
@LindseyD Thanks! I agree, we both have good answers to have here. –  Simon Kuran Aug 10 at 0:01

You can do that by using the next parameter...

{% for block in entry.myMatrixField %}
    {% if block.next %}
        <p>Next block type is: {{ block.next.type }}</p>
    {% endif %}
{% endfor %}

It's important to check {% if block.next %}, because the last block won't have a "next". If you were to try to call block.next.type where there is no "next", an error will be thrown.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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