Jump to content

Repeater containing if statement to execute HTML code after X iterations


Michkael
 Share

Recommended Posts

Hey Guys,

I have a repeater field containing 6 elements. Each element contains an headline, an image and a body field.
The page is set up to have 3 elements in a row and 3 in a new row (see image).
In the HTML code I am migrating into processwire, after 3 of the 6 elements, a <div class="row">...</div> forces the 3 new items on a new line.
The problem is that I cannot put this div inside the foreach otherwise all the elements would be in a column 1x6 instead than in a matrix 3x2.

I was thinking to code a counter $counter = 0 that increment during each iteration and when its value is 2 or 3 (depending on where the $counter++ is inserted) it executes the HTML code <div class="row"> and it reset the counter to 0 to allow further scalability.
Right now the actual code gives the result shown in the image.

Let me know if I am missing some details. Thank you guys.

  <section id="services" class="mea-service-section section-padding-shorter">
    <div class="container">
      <div class="row">
        <!-- Section Titile -->
        <div class="col-md-6 mea-title-section wow animated slideInLeft" data-wow-delay=".2s">
          <h1 class="section-titile-bg"><?=$page->headline;?></h1>
          <h1 class="section-title"><?=$page->headline;?></h1>
        </div>
        <!-- Section Quote -->
        <div class="col-md-6 mea-section-quote wow animated slideInRight" data-wow-delay=".2s">
          <blockquote>
            <p><?=$page->body;?></p>
                    </blockquote>
        </div>
      </div>
      <div class="row mt-10">
      <?php  foreach($page->Services as $Service): ?>
          <?php
          $image = $Service->image;
          ?>
      <!-- Services Widget Section -->

      <div class="col-md-4 single-service-widget wow animated fadeInUp" data-wow-delay=".3s">
        <div class="media">
          <div class="media-left">
            <img src="<?=$image->url; ?>">
          </div>
          <div class="media-body">
            <h2 class="subtitle"><?=$Service->headline ?></h2>
            <p><?=$Service->body ?></p>
          </div>
        </div>
      </div>
    <?php endforeach; ?>
    </div>
  </div>
</section>

 

Capture.JPG

Link to comment
Share on other sites

58 minutes ago, Zeka said:

You can use new slices method for that.

Maybe you could if the number of items in the WireArray is fixed, but I'd say it's not the best approach if the number of items is variable or might change at some point. The slices() method divides however many items are in the WireArray into the given number of slices. So if there are 6 items and you do slices(2) you will have two slices of 3 items each. But if later there were 7 items you would have a slice of 4 items and a slice of 3 items, which would not be so good for the desired layout.

Instead I think you want something equivalent to array_chunk() which will divide the WireArray into chunks of a given number of items. See here for a WireArray implementation of array_chunk():

 

  • Like 3
Link to comment
Share on other sites

@Robin S Thanks for the clarification about 'slices' method. I was on mobile, so couldn't test it till now, but the description from the blog post made me think that it would work as array_chunk.  @Michkael sorry for confusing. Obviously, slices method is not the best solution in your case. 

One more example of implementing a chunk 

 

  • Like 2
Link to comment
Share on other sites

And as a 3rd option, use the PHP modulo feature: http://php.net/manual/en/language.operators.arithmetic.php

1. Set a variable, eg $i to 1

2. Iterate through your (Wire)array and add 1 to $i each time

3. At each iteration, check if $i%3 == 0 and if so, add your row html

Example below selects 6 random service items and splits into 2 columns x 3 rows. For each item that returns $i%2 == 0 (2nd row item) I add the class "col_last". Add classes, html as required for your frontend theme - guessing it's Bootstrap

<?php $services = $pages->get('name=services')->pgtb_services->findRandom(6);
$i = 1; 
foreach ($services as $item) :
            $colLast = "";
            if (($i%2) == 0) $colLast = 'col_last';
            $i++; ?>

            <div class="col_half service <?=$colLast?> nobottommargin">
                <article class=" boxFeature">
                    ...
                </article>
            </div>
        <?php endforeach; ?>

      

 

  • Like 2
Link to comment
Share on other sites

This stupid bootstrap div class="row" thing is really one of the main reasons why I love uikit's grid system so much. There it is as easy as this:

<div class="uk-child-width-1-1 uk-child-width-1-2@s uk-child-width-1-3@m" uk-grid>
  <div>item</div>
  <div>item</div>
  <div>item</div>
  <div>item</div>
  <div>item</div>
  <div>item</div>
  <div>item</div>
  <div>item</div>
  <div>item</div>
</div>

And you instantly get a nice grid that is stacked on mobile (full with), 2-column on small devices upwards and 3-column on medium devices upwards. No html-row elements and lots of further options (divider, modifying grid item order responsively etc).

But as you are limited to bootstrap I guess it might be worth taking a look at http://arnaudleray.github.io/pocketgrid/ to make your life easier.

  • Like 1
Link to comment
Share on other sites

@psy Thank you. 
I have tried this option but i get the following error (see image): Parse error: syntax error, unexpected '$i' (T_VARIABLE) in /vagrant/src/site/templates/home.php on line 154.

Here is the code:
 

      <div class="row mt-10">
      <?php  $i = 1;
          foreach($page->Services as $Service):
          $image = $Service->image;
          $colLast = "";
          if (($i%3) == 0) $colLast = 'row';
          $i++; ?>

      <!-- Services Widget Section -->

      <div class="col-md-4 <?=$colLast?> single-service-widget wow animated fadeInUp" data-wow-delay=".3s">
        <div class="media">
          <div class="media-left">
            <img src="<?=$image->url; ?>">
          </div>
          <div class="media-body">
            <h2 class="subtitle"><?=$Service->headline ?></h2>
            <p><?=$Service->body ?></p>
          </div>
        </div>
      </div>
    <?php endforeach; ?>
    </div>

@Robin S @Zeka Thank you, I will now try the method of the chuncks.

Capture.JPG

Link to comment
Share on other sites

@Michkael Sometimes when copy/pasting directly from forum code unexpected and hidden chars end up in the output. I suspect that's what happened here. The (pure) code works but when I copy/pasted to my IDE I found a hidden char after.... "colLast" = "row" in your code. No one's fault and I'm guessing Line 144 was $i++ that failed.

Also found that your code <?=colLast"?> had a weird space in it in my IDE.

Best practice when copy/pasting from forum code is to paste into a text only editor before copy/pasting into your template to remove any weird, hidden chars.

After that and with Bootstrap being your framework, <?=colLast?> in that place will not work for you.  Bootstrap needs the row class on its own eg:

<div class="row">
  <div class="col-md_6">
    ...
  </div>
</div>

To make it work for you, you could try adding a CSS class:

.col_last {
	clear: both;
}

to ensure the next item starts on a new line below the previous three

 

  • Like 1
Link to comment
Share on other sites

@Michkael Doh me! - the class to clear a row in your case needs to be on each 4th item... Recommended change:
 

<?php  $i = 1;
          foreach($page->Services as $Service):
          $image = $Service->image;
          $colFirst = "";
          if ($i%4 == 0) $colFirst = 'col_first';
          $i++; ?>

With CSS class:

.col_first {
	clear: both;
}

Remember to either type the above completely into your IDE or copy/paste into a text-only editor first

  • Like 1
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...