Michkael Posted December 1, 2018 Share Posted December 1, 2018 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> Link to comment Share on other sites More sharing options...
Zeka Posted December 1, 2018 Share Posted December 1, 2018 You can use new slices method for that. Take a look at these part of previous week's blog post http://processwire.com/blog/posts/processwire-3.0.119-and-new-site-updates/#new-wirearray-slices-method 1 Link to comment Share on other sites More sharing options...
Robin S Posted December 1, 2018 Share Posted December 1, 2018 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(): 3 Link to comment Share on other sites More sharing options...
Zeka Posted December 1, 2018 Share Posted December 1, 2018 @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 2 Link to comment Share on other sites More sharing options...
psy Posted December 1, 2018 Share Posted December 1, 2018 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; ?> 2 Link to comment Share on other sites More sharing options...
dragan Posted December 1, 2018 Share Posted December 1, 2018 Perhaps you could also just use CSS? https://css-tricks.com/almanac/selectors/n/nth-of-type/ or Flexbox. Link to comment Share on other sites More sharing options...
bernhard Posted December 1, 2018 Share Posted December 1, 2018 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. 1 Link to comment Share on other sites More sharing options...
Michkael Posted December 2, 2018 Author Share Posted December 2, 2018 @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. Link to comment Share on other sites More sharing options...
psy Posted December 3, 2018 Share Posted December 3, 2018 @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 1 Link to comment Share on other sites More sharing options...
psy Posted December 3, 2018 Share Posted December 3, 2018 @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 1 Link to comment Share on other sites More sharing options...
Michkael Posted December 3, 2018 Author Share Posted December 3, 2018 It worked! Thank you @psy I have learn an important lesson about copy paste. 1 Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now