Jump to content
mike62

Displaying the most recent blog posts using different layouts for each

Recommended Posts

I'm new to PW... I'd like to have some blog posts displayed on our homepage based off the attached mockup.

I want each post to use a slightly different layout.

Is this possible?

blog-posts.jpg

Share this post


Link to post
Share on other sites

Here are two ways:

<?php namespace ProcessWire;
/** @var $pages Pages */
$posts = $pages->find('template=post, sort=-published');
$latest = $posts->shift(); // removes first item off of $posts

?>
<ul class="post-list">
    <li class="item--latest item">
        <?= $latest->title ?>
    </li>
    <?php if ($posts->count): ?>
        <?php foreach ($posts as $i => $p): ?>
            <?php $itemClass = ($i % 3 == 0) ? "item--hoverable" : ''; ?>
            <li class="<?= $itemClass ?> item"><?= $p->title ?></li>
        <?php endforeach; ?>
    <?php endif; ?>
</ul>

<!-- OR -->
<?php if ($posts->count): ?>

    <ul class="post-list">
        <?php foreach ($posts as $i => $post): ?>
            <?php if ($i === 0): // LATEST POST ?>
                <li class="item--latest item">
                    Latest: <?= $post->title ?>
                </li>
            <?php elseif ($i === 1): // BASIC ?>
                <li class="item--basic item">
                    Basic: <?= $post->title ?>
                </li>
            <?php elseif ($i % 3 === 0): // HOVERABLE  ?>
                <li class="item--hoverable item">
                    Hover Me: <?= $post->title ?>
                </li>
            <?php endif; ?>
        <?php endforeach; ?>
    </ul>
<?php else: ?>
    <p>No posts found</p>
<?php endif; ?>

 

Edited by abdus
changed semicolon to colon
  • Like 2

Share this post


Link to post
Share on other sites

Optionally, you can create a select field, or better, a page field and select flavors for each post while editing and render items depending on that

https://processwire.com/blog/posts/making-efficient-use-of-fields-in-processwire/#use-page-fields-rather-than-individual-checkboxes

if($item->flavors->get("name=hoverable")) {
    // this page has the "hoverable" flavor set
}
  • Like 2

Share this post


Link to post
Share on other sites

Ooooh wonderful, that's excellent to know. I likely won't use it for this site, because they want the layout to remain the same on the homepage, and have the content just flow into it, but good to know for the future. Thanks!!

Share this post


Link to post
Share on other sites

@abdus I've got this *almost* working... but I'm stumped with simply getting the sort order to be reversed, so that the newest post shows at the top. Also, can I easily limit this query to 4 posts? Thanks!

Share this post


Link to post
Share on other sites

@kongondo Thanks! I literally JUST found both those in the docs. Some things are hard for me to find in these docs. Is there a way to search *just* the docs, on the site?

Share this post


Link to post
Share on other sites
2 minutes ago, mike62 said:

@kongondo Thanks! I literally JUST found both those in the docs. Some things are hard for me to find in these docs. Is there a way to search *just* the docs, on the site?

https://processwire.com/talk/topic/6196-easy-search-on-pw-forums-with-google/?tab=comments#comment-60632

https://processwire.com/talk/topic/6196-easy-search-on-pw-forums-with-google/?do=findComment&comment=153343

 

  • Like 1

Share this post


Link to post
Share on other sites
3 minutes ago, mike62 said:

*just* the docs, on the site?

I bookmarked these and update the search word after clicking them and press enter. I know it's crude but it is the fastest way for me :-[

Share this post


Link to post
Share on other sites

Thanks for the tip @Robin S I cannot se how it can be faster than my dead simple solution. Sure, I perform an otherwise useless search but Google is sooo fast ;)

With the "keyword search feature", I need to be able to remember the keyword(s). Well, I already use a lot of them in other contexts so I find it hard to memorize more. Next, I need to type the get there. One click in the Bookmarks Bar and another double click to highlight the dummy search word is what I can do quickly without mistakes. Yeah, it's lame but it works for me.

Share this post


Link to post
Share on other sites

Cool, thanks @SamC that's a good one to know. I ended up using the page field as @abdus suggested, so that each post can "choose" its own layout for the homepage. It's working well. o/

  • Like 2

Share this post


Link to post
Share on other sites
12 minutes ago, mike62 said:

Cool, thanks @SamC that's a good one to know. I ended up using the page field as @abdus suggested, so that each post can "choose" its own layout for the homepage. It's working well. o/

Good to hear! That's a nice technique, will certainly be looking into that one.

Share this post


Link to post
Share on other sites

Hey @SamC  I was looking for a way to style some results of a selector differently than others and found your 'slicing' suggestion fitting perfectly to my scenario. Here is a short example of what I have and would allow any results from to be styled one way and the rest - another:

<?php 			
	// Check if there are any news added
	if (count($news->children)) {
		
		// Create am array with the latest 5 news
		$newsposts = $pages->find("template=news-inner, status=published, sort=-date, limit=6");
		
		// Create a slice of 2 posts for the large image style
		// 0 means the starting record, 2 means the number of records to slice
		$left = $newsposts->slice(0,2);
		
		// Grab the rest of the posts from the list for styling with just a title and a date
		// 2 means that everything except the first two would be assigned.
		// The results limit is set initially at the selector
		$right = $newsposts->slice(2);
		
	}
?>

Having done that, it allowed me to simply loop through the $left and $right results (using foreach) and apply the proper markup for first appearance and the rest. Using this elegant technique would allow to have as many slices for different styling if a need be.

Unfortunately, my markup for the first news was in a row div that was closing before the rest of the posts appear in another row so I had to loop twice with foreach. I am sure there is a better way to include the opening and closing divs to avoid double/tripple etc. looping but as far as the result are not more than 6, I am not that worried about slowing the page down...

Share this post


Link to post
Share on other sites
3 hours ago, MilenKo said:

I was looking for a way to style some results of a selector differently than others

If it's just styling, you should first try a CSS-only solution. You can do a lot with just :nth-child or flexbox.

  • Like 1

Share this post


Link to post
Share on other sites

Thanks @dragan will try your approach to see how would that fit, however it is not just styling but the markup is different where the first 2 news are required to have a large image with some intro text, author, date, likes etc. where the next 4 are just title and date of posting.

That is why initially I thought to "slice" the array but it did not work properly so with $a->slice it did the trick. I will see how to serve the posts with a single foreach to avoid duplication, however the classes of divs are different, some javas are included in the no-image divs and some data handling. Not sure if I add a variable for the class, one for the javas and one for data- values to include in the div which one would be faster since I am looping once through 2 results and once through 4 others.

Maybe I could try using modulus operator or other approach as well ?

Share this post


Link to post
Share on other sites

Well I initially tried with the good old counter approach but things got messed up a bit because of the differences in the markup of large image post and others. Will revise the code and see how to include the opening and closing divs properly. Here is the markup I am working with:

Spoiler

<div class="row">

	<!-- Large image post x 2 -->
	<div class="news-block col-lg-4 col-md-6 col-sm-12 wow fadeInUp animated" style="visibility: visible; animation-name: fadeInUp;">
		<div class="inner-box">
			<div class="image-box">
				<figure class="image"><a href="#"><img src="images/resource/news-1.jpg" alt=""></a></figure>
			</div>
			<div class="lower-content">
				<div class="date">26 Aug. 2018</div>
				<h5><a href="blog-detail.html">Mac Keychain Bug Could Be Big Problem For Apple</a></h5>
				<div class="text">Fed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt ...</div>
				<div class="link-box"><a href="blog-detail.html">Read more</a></div>
			</div>
		</div>
	</div>


	<!-- News Block -->
	<div class="news-list col-lg-4 col-md-12 col-sm-12 wow fadeInUp animated" data-wow-delay="800ms" style="visibility: visible; animation-delay: 800ms; animation-name: fadeInUp;">
		<div class="inner-box">
		
			<!-- List Item x 4 -->
			<div class="list-item">
				<h5><a href="blog-detail.html">Nanotechnology immersion along the information.</a></h5>
				<span class="date">Aug 26 2018</span>
			</div>

		</div>
	</div>
</div>

 

Where Large image post shows twice and List Item show 4 times 😉

Share this post


Link to post
Share on other sites
9 minutes ago, MilenKo said:

<div class="news-block col-lg-4 col-md-6 col-sm-12 wow fadeInUp animated"

<div class="news-list col-lg-4 col-md-12 col-sm-12 wow fadeInUp animated" data-wow-delay="800ms"

I like the developer satisfacion coming through these lines 🙂 

  • Like 1
  • Haha 1

Share this post


Link to post
Share on other sites

@tpr Tell me about it 🙂 Just because of the div opening markup I was crushing my head for some time before I "split" the selector in two and then applied the every foreach inside of every div 😉 This could all goe to the CSS but hey - different people, different taste 🙂

Share this post


Link to post
Share on other sites

Guess you could be clever with modulus and some dynamic class names etc. Or, just go for two loops and call it a day. I did something before and tried to be uber clever about it, turns out it's not so clever when you go back and have to waste time working out how it works.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By MoritzLost
      In this tutorial I want to write about handling special cases and change requests by clients gracefully without introducing code bloat or degrading code quality and maintainability. I'll use a site's navigation menu as an example, as it's relatable and pretty much every site has one. I'll give some examples of real situations and change requests I encountered during projects, and describe multiple approaches to handling them. However, this post is also about the general mindset I find useful for ProcessWire development, which is more about how to handle special cases and still keep your code clean by making the special case a normal one.
      The problem: Special cases everywhere
      Since ProcessWire has a hierarchical page tree by default, as a developer you'll usually write a function or loop that iterates over all children of the homepage and displays a list of titles with links. If the site is a bit more complex, maybe you additionally loop over all grandchildren and display those in drop-down menus as well, or you even use a recursive function to iterate over an arbitrary amount of nested child pages. Something like this:
      function buildRecursiveMenu(Page $root): string { $markup = ['<ul class="navigation">']; foreach ($root->children() as $child) { $link = '<a class="navigation__link" href="' . $child->url() . '">' . $child->title . '</a>'; $children = $child->hasChildren() ? buildRecursiveMenu($child) : ''; $markup[] = "<li class="navigation__item">{$link}{$children}</li>"; } $markup[] = '</ul>'; return implode(PHP_EOL, $markup); } But then the requests for special cases come rolling in. For example, those are some of the requests I've gotten from clients on my projects (by the way, I'm not saying the clients were wrong or unreasonable in any of those cases - it's simply something I needed to handle in a sensible way):
      The homepage has the company's name as it's title, but the menu link in the navigation should just say "Home". The first page in a drop-down menu should be the top-level page containing the drop-down menu. This was requested because the first click on the top-level item opens the sub-navigation instead of navigating to that page (espcially on touch devices, such as iPads, where you don't have a hover state!), so some visitors might not realize it's a page itself. Some top-level pages should be displayed in a drop-down menu of another top-level page, but the position in the page tree can't change because of the template family settings. The menu needs to contain some special links to external URLs. For one especially long drop-down menu, the items should be sorted into categories with subheadings based on a taxonomy field. In general, my solutions to those requests fall into three categories, which I'll try to elaborate on, including their respective benefits and downsides:
      Checking for the special case / condition in the code and changing the output accordingly (usually with hard-coded values). Separating the navigation menu from the page tree completely and building a custom solution. Utilizing the Content Management Framework by adding fields, templates and pages that represent special states or settings. Handling it in the code
      This is the simplest solution, and often the first thing that comes to mind. For example, the first request (listing the homepage as "Home" instead of it's title in the navigation) can be solved by simply checking the template or ID of the current page inside the menu builder function, and changing the output accordingly:
      // ... $title = $child->template->name === 'home' ? 'Home' : $child->title; $link = '<a class="navigation__link" href="' . $child->url() . '">' . $title . '</a>'; // ... This is definitely the fastest solution. However, there are multiple downsides. Most notably, it's harder to maintain, as each of those special cases increases the complexity of the menu builder function, and makes it harder to change. As you add more special conditions, it becomes exponentially harder to keep changing it. This is the breeding ground for bugs. And it's much harder to read, so it takes longer for another developer to pick up where you left (or, as is often cited, for yourself in six months). Also, now we have a hard-coded value inside the template, that only someone with access to and knowledge of the template files can change. If the client want's the link to say "Homepage" instead of "Home" at some point, they won't be able to change it without the developer. Also, each special case that is hidden in the code makes it harder for the client to understand what's going on in terms of template logic - thus increasing your workload in editorial support.
      That said, there are definitely some times where I would go with this approach. Specifically:
      For smaller projects that you know won't need to scale or be maintained long-term. If you are the only developer, and/or only developers will edit the site, with no "non-technical" folk involved. For rapid prototyping ("We'll change it later") Building a custom solution
      My initial assumption was that the main navigation is generated based on the page tree inside ProcessWire. But of course this isn't set in stone. You can just as easily forgo using the page tree hierarchy at all, and instead build a custom menu system. For example, you could add a nested repeater where you can add pages or links on a general settings page, and generate the menu based on that. There are also modules for this approach, such as the Menu Builder by @kongondo. This approach is not the quickest, but gives the most power to the editors of your site. They have full control over which pages to show and where. However, with great power comes great responsibility, as now each change to the menu must be performed manually. For example, when a new page is added, it won't be visible in the menu automatically. This is very likely to create a disconnect between the page tree and the menu (which may be what you want, after all). You may get ghost pages that are not accessible from the homepage at all, or the client may forgot to unpublish pages they don't want to have any more after they've removed them from the menu.
      I would only go with this approach if there are so many special cases that there hardly is a "normal case". However, even then it might not be the best solution. The direct relationship between the page tree, the menu structure and page paths are one of the strongest features of ProcessWire in my opinion. If many pages need to be placed in special locations without much structure in regards to what templates go where, maybe you only need to loosen up the template family settings. I have built one site without any template family restrictions at all - any page of any template can go anywhere. It's definitely a different mindset, but in this case it worked well, because it allowed the client to build custom sections with different page types grouped together.
      It's a trade-off, as it is so often, between flexibility and workload. Weigh those options carefully before you choose this solution!
      Utilizing the CMF
      This is the middle ground between the two options above. Instead of building a completely custom solution, you keep with the basic idea of generating a hierarchical menu based on the page tree, but add fields and templates that allow the editor to adjust how and where individual pages are displayed, or to add custom content to the menu. of course, you will still write some additional code, but instead of having hard-coded values or conditions in the template, you expose those to the client, thereby making the special case one of the normal cases. The resulting code is often more resilient to changing requirements, as it can not one handle that specific case that the client requested, but also every future change request of the same type. The key is to add fields that enable the client to overwrite the default behaviour, while still having sensible defaults that don't require special attention from the editor in most cases. I'll give some more examples for this one, as I think it's usually the best option.
      Example 1: Menu display options
      This is probably the first thing you thought of for the very first change request I mentioned (displaying the homepage with a different title). Instead of hard-coding the title "Home" in the template, you add a field menu_title that will overwrite the normal title, if set. This is definitely cleaner than the hard-coded value, since it allows the client to overwrite the title of any page in the menu.
      I'll only say this much in terms of downsides: Maybe the menu title isn't really what the client wanted - instead, perhaps they feel limited because the title is also displayed as the headline (h1) of the page. In this case, the sensible solution would be an additional headline field that will overwrite the h1, instead of the menu_title field. Which fields are really needed is an important consideration, because you don't want to end up with too many. If each page has fields for the title, a headline, a menu title and an SEO-title, it's much more complicated than it needs to be, and you will have a hard time explaining to the client what each field is used for.
      Another example in this category would be an option to "Hide this page in the menu". This could be accomplished by hiding the page using the inbuilt "hidden" status as well, but if it's hidden it won't show up in other listings as well, so separating the menu display from the hidden status might be a good idea if your site has lots of page listings.
      Example 2: "Menu link" template
      One solution that is quite flexible in allowing for custom links to pages or external URLs is creating a menu-link template that can be placed anywhere in the page tree. This templates can have fields for the menu title, target page and/or external target URL. This way, you can link to another top-level page or an external service inside a drop-down menu, by placing a Menu Link page at the appropriate position. This is also a clean solution, because the navigation menu will still reflect the page tree, making the custom links visible and easily editable by the editors.
      A minor downside is that those templates are non-semantical in the sense that they aren't pages with content of their own. You'll need to make sure not to display them in listings or in other places, as they aren't viewable. It may also require loosening up strict family rules - for example, allowing for Menu Link pages to be placed below the news index page, which normally can only hold news pages.
      Example 3: Drop-down menu override
      This one is a more radical solution to override drop-down menus. You add a repeater field to top-level pages, similar to the one mentioned as a custom solution, where you can add multiple links to internal pages or URLs. If the repeater is empty, the drop-down menu is generated normally, based on the sub-pages in the page tree. But if the repeater contains some links, it completely overrides the drop-down menu. It's similar to the fully custom solution in that as soon as you override a sub-menu for a top-level page, you have to manually manage it in case the page structure changes. But you can make that decision for each top-level page individually, so you can leave some of them as is and only have to worry about the ones that you have overwritten.
      Again, this offers sensible defaults with good customizability. A downside is that the mixed approach may confuse the client, if some changes to the page tree are reflected in the drop-down menu directly, while others don't seem to have any effect (especially if you have multiple editors working on a site).
      Finding the right solution
      So how do you choose between the approaches? It depends on the client, the requirements, and on what special cases you expect and want to handle. Sometimes, a special request can be turned down by explaining how it would complicate editorial workflows or have a negative impact on SEO (for example, if you risk having some pages not accessible from the homepage at all). Also, make sure you understand the actual reason behind a change request, instead of just blindly implementing the suggestion by the client. Often, clients will suggest solutions without telling you what the actual problem is they're trying to solve.
      For example: In one case, I implemented the drop-down override mentioned in example three. However, what the client really wanted was to have the top-level page as the first item in the drop-down menu (see the example requests mentioned above). So they ended up overwriting every single drop-down menu, making the menu harder to maintain. In this case, it would have been better to go with a more specialized solution, such as adding a checkbox option, or even handling it in the code, since it would have been consistent throughout the menu.
      Another example was mentioned above: If the client requests an additional "Menu title" field, maybe what they really need is a "Headline" field. I recommend reading Articulating Design Decisions by Tom Greever; it includes some chapters on listening to the client, finding out the real reason behind a change request, and responding appropriately. It's written from a design perspective, but is applicable to development as well, and since UX becomes more important by the day, the lines between the disciplines are blurred anyway.
      Conclusion
      I realize now this reads more like a podcast (or worse, a rant) than an actual tutorial, but hopefully I got my point across. ProcessWire is at is greatest if you utilize it as a Content Management Framework, creating options and interfaces that allow for customizability while retaining usability for the client / editor. I usually try to hit a sweet spot where the editors have maximum control over the relevant aspects of their site, while requiring minimal work on their part by providing sensible defaults. Above, I listed some examples of requests I've gotten and different solutions I came up with to handle those with custom fields or templates. Though in some cases the requirements call for a custom solution or a quick hack in the template code as well!
      What are some of the special requests you got? How did you solve them? I'd love to get some insights and examples from you. Thanks for reading!
    • By Mithlesh
      Changing it to null
    • By Mithlesh
      Hi, I have one URL - writerrelocations.com/contact-now/

      I have one issue where my header Image is appearing again after the contact form, for your reference:



      I have checked my processwire template section where have not added any Image field besides Header Image, attaching the same for the reference:




      PLEASE help me to get rid of the image below contact form

      Waiting for the swift response!

      Thanks
       
    • By Liam88
      Hi all,
      Quick question as I haven't found anything from my Googling. 
      I have a blog on the site which utilises pagination. On the standard blog page I have a custom header which has featured posts.
      Below that I then have recent posts like mosts blogs.
      Now if i click to page two or three I want the header to disappear and just show a continuation of the standard posts.
      I'm not sure how to go about this so any direction would be helpful.
      Thanks
    • By Violet
      Here I'm introducing FlipFall Magazine, our multi-topic blog. It used to run on Wordpress but we recently switched it to ProcessWire. This was done the usual way we do it when converting our sites: install ProcessWire in a subfolder of the original Wordpress site under a hard-to-guess name, set up the new site there, then move content over manually, inspecting and updating each article as needed. After the ProcessWire site was ready, when we un-installed the Wordpress one and moved the ProcessWire site up one level to the document root, and... done.
      We used the W3CSS framework because it handles the responsive breakpoints so well (no extra work for us 😉), and it tends to default to a clean modern look.
      We wanted full control over the back end of the site and do customized things without having to hire a developer.  As FlipFall has grown, the ability to have in-house back-end control has become even more important.
      Case example: Ad partners - we now can quite easily, if we wish, place different ads on different topics on this blog at a moment's notice - no need to hire a developer. Changes like this can be implemented in-house right away. The fact that we can easily incorporate this sort of thing is really nice when we're talking with potential ad partners.
      Helpful features of ProcessWire during this experience:
      The ability to export and import fields in PW was key here. We had a few other article-style sites I had done in PW recently, so having the same types of templates was very helpful. We were able to export fields and templates from our existing sites and import into FlipFall as a starting base point. No need to re-invent the wheel here! Another helpful ability of PW was when we were dealing with the categories. We built the site without category templates (but with the category page field), then added the templates in later as needed - no disruption. In other words, a template-less page field worked perfectly for the categories until we needed the template, then we just created the template. Not every feature of the site needs to be thought out in absolute full beforehand, some can be added in later as needed. Very extensible and convenient. Internal links within blog posts worked well using the page select option in the link button on the editor. When moving out of staging folder and into document root, the links auto-updated, which was nice. Creating new articles is a breeze, because under PW our fields are now customized for our needs: we created all of the fields we need and none of the ones we don't. Again, this is unlike most blogging CMS's, where they try to guess what you want (and usually get it wrong). Even for people who are solely doing blogs/article sites, I feel that ProcessWire is a much better option than most blog-specific platforms, because of PW's flexibility.  The only thing I miss about Wordpress is the ability to auto-schedule post publication, which for the serious blogger is important. For example, there were some occasions on some of our other blogs where we needed to schedule posts to auto-publish at 3:01am Eastern Time to allow a time-sensitive post to come out as early in time of day as possible on publication date (3:01 am US Eastern time ensures it's that same day 12:01 am on Pacific time). We were delighted to see that ProcessWire is much, much lighter on resources of the hosting environment than the same site on Wordpress - we could see this empirically on our web hosting stats before and after the switch.
×
×
  • Create New...