Answers.Body: <p>I always think of this sort of thing as a <a href="https://en.wikipedia.org/wiki/Finite-state_machine" rel="nofollow noreferrer">finite state machine</a>. 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:</p>
  
  <pre><code>{# 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 #}
      &lt;div&gt;
      {% set inTheDiv = true %}
    {% endif %}
    {% if not isInsideBlock and inTheDiv %}
      {# state change to not inTheDiv #}
      &lt;/div&gt;
      {% set inTheDiv = false %}
    {% endif %}
  
    ... output your block stuff here
  {% endfor %}
  
  {# done with blocks, so close the div if necessary #}
  {% if inTheDiv %}
    &lt;/div&gt;
    {% set inTheDiv = false %}
  {% endif %}
  </code></pre>
  
  <p>The whole finite state machine may seem like overkill, but you can handle a lot of complexity this way.</p>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2018-01-29T17:59:44.430Z
Answers.Text: 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?
Answers.UserDisplayName: Terry Upton
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2018-01-29T18:14:18.163Z
Answers.Text: 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.
Answers.UserDisplayName: Terry Upton
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2018-01-29T20:16:58.757Z
Answers.Text: 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.
Answers.UserDisplayName: Marion Newlevant
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2018-01-29T20:27:18.993Z
Answers.Text: 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 :-)
Answers.UserDisplayName: Terry Upton
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2018-01-28T19:22:08.143Z
Answers.LastActivityDate: 2018-01-28T19:22:08.143Z
Answers.UserDisplayName: Marion Newlevant
Body: <p>How can I wrap a div around certain neo fields based on what appears before or after them?</p>
  
  <p>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.</p>
  
  <p>I started with this but I am a little stuck</p>
  
  <pre><code>{% 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
          &lt;div class="max-w-2xl // min-w-75 // mx-auto //  //// px-6 // border //"&gt;
        {% endif %}
  
  {% if prevType in ['heading', 'body', 'downloads', 'textLinks'] %}
        &lt;/div&gt;
      {% endif %}
  </code></pre>
  
  <p>The above code currently wraps a div around each instance of the array not one around the group.</p>
  
  <p>UPDATE:<br>
  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;</p>
  
  <pre><code>{% 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 %}
      &lt;div class="mx-auto // max-w-2xl border border-red //// py-4"&gt;
    {% 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' %}
        &lt;div class="-mx-6 //// {{ block.sectionSpacing }}"&gt;
          {% include '_includes/matrix3/tabbedContent' %}
        &lt;/div&gt;
  
      {% case 'tiles' %}
        &lt;div class="{% if fullWidth == true %}-mx-6{% else %}mx-auto // max-w-4xl flex{% endif %} //// {{ block.sectionSpacing }}"&gt;
          {% include '_includes/matrix3/tiles' %}
        &lt;/div&gt;
  
      {% case 'tileWithImage' %}
        &lt;div class="{% if fullWidth == true %}-mx-6{% else %}mx-auto // max-w-2xl{% endif %} //// {{ block.sectionSpacing }}"&gt;
          {% include '_includes/matrix3/tileWithImage' %}
        &lt;/div&gt;
  
      {% case 'textWithImage' %}
        &lt;div class="mx-auto // max-w-2xl //// {{ block.sectionSpacing }}"&gt;
          {% include '_includes/matrix3/textWithImage' %}
        &lt;/div&gt;
  
      {% 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' %}
        &lt;div class="{{ block.sectionSpacing }}"&gt;
          {% include '_includes/matrix3/mediaGrid' %}
        &lt;/div&gt;
  
      {# CTA BLOCKS #}
      {% case 'callToActionFull' %}
        &lt;div class="-mx-6 //// {{ block.sectionSpacing }}"&gt;
          {% include '_includes/matrix3/callToActionFull' %}
        &lt;/div&gt;
  
      {% case 'callOutBlock' %}
        &lt;div class="-mx-6 //// {{ block.sectionSpacing }}"&gt;
          {% include '_includes/matrix3/callOutBlock' %}
        &lt;/div&gt;
  
    {% endswitch %}
  
    {% if type in textBlockArray and nextType not in textBlockArray and prevType in textBlockArray %}
      &lt;/div&gt;
    {% endif %}
  
  {% endfor %}
  </code></pre>
  
Comments.ContentLicense: CC BY-SA 3.0
Comments.CreationDate: 2018-01-29T20:40:54.603Z
Comments.Text: I'm glad you got it working. I notice that in your update, you are setting `inTheDiv`, but never actually referring to it.
Comments.UserDisplayName: Marion Newlevant
Comments.ContentLicense: CC BY-SA 3.0
Comments.CreationDate: 2018-01-29T20:44:04.850Z
Comments.Text: 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.
Comments.UserDisplayName: Terry Upton
Comments.ContentLicense: CC BY-SA 3.0
Comments.CreationDate: 2018-01-29T22:00:01.543Z
Comments.Text: 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.
Comments.UserDisplayName: Marion Newlevant
Tags: <templating><plugin-neo>
Title: Wrapping divs around a group of neo blocks
ThreadText: # Wrapping divs around a group of neo blocks
  
  (Asked by: username_0 on 2018-01-27)
  
  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 %}
  
  ```
  
  **Tags:** templating, plugin-neo
  
  > **Comments:**
  > **username_1**: I'm glad you got it working. I notice that in your update, you are setting `inTheDiv`, but never actually referring to it.  
  > **username_0**: 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.  
  > **username_1**: 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.  
  
  ---
  
  ## 1 answers
  
  ### Answer by username_1 on 2018-01-28. Score: 3
  
  I always think of this sort of thing as a [finite state machine](https://en.wikipedia.org/wiki/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.
  
  > **Comments:**
  > **username_0**: Thanks for this @username_1 - 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?  
  > **username_0**: 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.  
  > **username_1**: 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.  
  > **username_0**: 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 :-)  
  
  ---
  
  