2

How can I wrap a div around certain neo fields based on what appears before or after them?

Basically I want to wrap a container div around a set of items (text based objects) only at the start and end of these objects but whenever they appear. Sometimes they might have one item other times they migjt have several.

I started with this but I am a little stuck

{% for block in entry.contentBuilder3.level(1) %}
      {% set type = block.type.handle %}
      {% set nextType = (not loop.last ? type) %}
      {% set prevType = (not loop.last ? type) %}

      {% if type in ['heading', 'body', 'downloads', 'textLinks' ]  %}
       {{ nextType }} :: {{ prevType }} this is a first child
        <div class="max-w-2xl // min-w-75 // mx-auto //  //// px-6 // border //">
      {% endif %}

{% if prevType in ['heading', 'body', 'downloads', 'textLinks'] %}
      </div>
    {% endif %}

The above code currently wraps a div around each instance of the array not one around the group.

UPDATE:
After Marions helpful answer, I was unable to solve exactly with her method, but it did put me on the right tracks to solve it like so;

{% set inTheDiv = false %}
{% set nextType = null %}
{% set prevType = null %}

{% for block in entry.contentBuilder3.level(1) %}
  {% set type = block.type.handle %}
  {% set nextType = (not loop.last ? block.next.type.handle) %}
  {% set prevType = (not loop.first ? block.prev.type.handle) %}
  {% set fullWidth = block.fullWidth|default() %}
  {% set textBlockArray = ['heading', 'body', 'downloads', 'textLinks', 'pullQuote', 'callToActionText'] %}

  {% if type in textBlockArray and nextType in textBlockArray and prevType not in textBlockArray %}
    <div class="mx-auto // max-w-2xl border border-red //// py-4">
  {% endif %}

  {% switch type %}

    {# BLOCK TYPES CONTNET/TEXT #}
    {% case 'heading' %}
      {{ sectionSpacing }}
    {% include '_includes/matrix3/heading' %}

    {% case 'body' %}
      {% include '_includes/matrix3/body' %}

    {% case 'pullQuote' %}
      {% include '_includes/matrix3/pullQuote' %}

    {% case 'downloads' %}
      {% include '_includes/matrix3/downloads' %}

    {% case 'textLinks' %}
      {% include '_includes/matrix3/textLinks' %}

    {% case 'callToActionText' %}
      {% include '_includes/matrix3/callToActionText' %}

    {% case 'quote' %}
      {% include '_includes/matrix3/quote' %}

    {# LAYOUT BLOCKS #}
    {% case 'tabbedContent' %}
      <div class="-mx-6 //// {{ block.sectionSpacing }}">
        {% include '_includes/matrix3/tabbedContent' %}
      </div>

    {% case 'tiles' %}
      <div class="{% if fullWidth == true %}-mx-6{% else %}mx-auto // max-w-4xl flex{% endif %} //// {{ block.sectionSpacing }}">
        {% include '_includes/matrix3/tiles' %}
      </div>

    {% case 'tileWithImage' %}
      <div class="{% if fullWidth == true %}-mx-6{% else %}mx-auto // max-w-2xl{% endif %} //// {{ block.sectionSpacing }}">
        {% include '_includes/matrix3/tileWithImage' %}
      </div>

    {% case 'textWithImage' %}
      <div class="mx-auto // max-w-2xl //// {{ block.sectionSpacing }}">
        {% include '_includes/matrix3/textWithImage' %}
      </div>

    {% case 'textWithVideo' %}
      {% include '_includes/matrix3/textWithVideo' %}

    {% case 'textWithText' %}
      {% include '_includes/matrix3/textWithText' %}


    {% case 'statistics' %}
      {% include '_includes/matrix3/statistics' %}

    {# MEDIA BLOCKS #}
    {% case 'image' %}
      {% include '_includes/matrix3/image' %}

    {% case 'video' %}
      {% include '_includes/matrix3/video' %}

    {% case 'mediaGrid' %}
      <div class="{{ block.sectionSpacing }}">
        {% include '_includes/matrix3/mediaGrid' %}
      </div>

    {# CTA BLOCKS #}
    {% case 'callToActionFull' %}
      <div class="-mx-6 //// {{ block.sectionSpacing }}">
        {% include '_includes/matrix3/callToActionFull' %}
      </div>

    {% case 'callOutBlock' %}
      <div class="-mx-6 //// {{ block.sectionSpacing }}">
        {% include '_includes/matrix3/callOutBlock' %}
      </div>

  {% endswitch %}

  {% if type in textBlockArray and nextType not in textBlockArray and prevType in textBlockArray %}
    </div>
  {% endif %}

{% endfor %}
  • I'm glad you got it working. I notice that in your update, you are setting inTheDiv, but never actually referring to it. – Marion Newlevant Jan 29 '18 at 20:40
  • Ah yes. Thanks. A hangover from working through it from your example. I will clean this up. Can you see from what I have done as to how your solution might have worked? I would like to see if I can improve or do it better if possible. – Terry Upton Jan 29 '18 at 20:44
  • Well, I still haven't seen where my solution doesn't work, but then I haven't actually tried it, so I don't know where it went wrong. – Marion Newlevant Jan 29 '18 at 22:00
3

I always think of this sort of thing as a finite state machine. Your states are whether or not you are in the div, and for each block, you change state or not depending on what state you are currently in, and what that block type is. Like this:

{# initial state: not in the div #}
{% set inTheDiv = false %}

{% for block in blocks %}
  {# should this block be inside the div? #}
  {% set isInsideBlock = block.type.handle in ['heading', 'body', 'downloads', 'textLinks'] %}

  {% if isInsideBlock and not inTheDiv %}
    {# state change to inTheDiv #}
    <div>
    {% set inTheDiv = true %}
  {% endif %}
  {% if not isInsideBlock and inTheDiv %}
    {# state change to not inTheDiv #}
    </div>
    {% set inTheDiv = false %}
  {% endif %}

  ... output your block stuff here
{% endfor %}

{# done with blocks, so close the div if necessary #}
{% if inTheDiv %}
  </div>
  {% set inTheDiv = false %}
{% endif %}

The whole finite state machine may seem like overkill, but you can handle a lot of complexity this way.

  • Thanks for this @marionnewlevant - not sure if I have understood this correctly, but this seems to wrap a div around each of the isInsideBlock items rather than one div around all of them when in a group? – Terry Upton Jan 29 '18 at 17:59
  • What I am trying to achieve is to have a container div wrapper around the the blocks in the array as a group not individually. – Terry Upton Jan 29 '18 at 18:14
  • It absolutely should wrap a div around them as a group. You open the div when you start the group, you close it when you end the group. The state machine keeps track of are you in the group or not. – Marion Newlevant Jan 29 '18 at 20:16
  • I have added an update to my original question. I wasn't able to solve it using your method, but it did help me on the right track. I have added my full code into my original question, you might be able to see where I was going wrong? Thanks :-) – Terry Upton Jan 29 '18 at 20:27

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.