Jump to content

Outputting nested contents of page children/grandchildren


martinluff
 Share

Recommended Posts

Hi guys

I have a page ('how-it-works') in a website where I'm looping through its child pages and in turn any grandchildren to output their titles and body content into a single page so it looks like one long article (it's a long information doc with lots of clauses and sub-clauses and different people updating different parts of it so client asked to have each part as separate article). I took a look at Ryan's example code in the demo sites plus the two postings on the forum here http://processwire.com/talk/index.php/topic,128.0.html and http://processwire.com/talk/index.php/topic,26.0.html but they didn't seem to do quite what I wanted to I cobbled together the following which works...

<?php    $morePoints = $pages->get("/details/how-it-works/")->children;
   foreach ($morePoints as $aPoint){
       $content .= "<div class='shide'><h2 class='morePoints'><a href='#'>{$aPoint->title}</a></h2></div>\n<div>{$aPoint->body}";
       	if($aPoint->numChildren) {
	$content .= "<ol>";
	foreach($aPoint->children as $subPoint) {$content .= "<li><div class='shide'><h3><a href='#'>{$subPoint->title}</a></h3></div><div>{$subPoint->body}</div></li>";}; 
	$content .= "</ol>";
}
       $content .= "</div>";
   }

...but (due to my very limited PHP/programming skills)  I'm concerned it's a pretty messy way of doing it. Would appreciate if anyone had a look at this and came up with any suggestions on how to improve it...

Thanks in advance  :)

Edit: updated this entry with leading <?php tag to pick up PHP source highlighting...

Link to comment
Share on other sites

Seems reasonable to me :)

If you had sub-sub-clauses then it would be best done with a recursive function that also keeps track of how many levels deep you are so you can alter the formatting accordingly (or just use CSS if you don't want the formatting at each level to be wildly different.

Recursion hurts my brain though so I tend to put it off until I really need it.

Link to comment
Share on other sites

From a PHP code side I think it looks fine. If you reduce it to just the logic (taking out all the needs of the markup), you've got this, which is pretty straightforward:

<?php
$content = "<pre>";

foreach($morePoints as $aPoint) {
    $content .= "\n" . $aPoint->title; 
    foreach($aPoint->children as $subPoint) {
        $content .= "\n\t" . $subPoint->title;
    }
}

This method does become messy if you once you get to a lot of nested levels, or an unknown number of levels. At that time, it's better to take a different approach (recursive function being the option I usually take).

Link to comment
Share on other sites

Hey, thanks Pete and Ryan. And there I was assuming I'd probably made a right 'dogs-dinner' of it  ;)

Yes, had thought it could get a bit messy if I was going down more levels... Now in this case I'm using rather different markup for the output from children and from grandchildren; would this be straight forward if I were using recursion or would it be a bit of a nightmare?

Thanks again for the feedback...

Link to comment
Share on other sites

If you were only going one more level deeper to grandchildren then I would just nest your foreach loop once again with the specific markup for grandchildren.

Recursion is the way to do it if you've got many more levels than that, or an unknown number of levels otherwise you could end up nesting almost exactly the same bit of code lots more times in your template, but you would have to have a counter to work out how many levels deep you are when printing a given title to know what formatting to apply to the title so I think in your specific case here recursion would just add unnecessary headaches and confusion.

Alternatively you could well use recursion and if they're list items then you can use CSS to style them if you don't want to do massively complicated things at each level - for example (and this is just off the top of my head so may not work):

<style>
ul#mylist li {
  /* Your style here for the first-level (parent) list item */
}

ul#mylist li li {
  /* Your style here for the second-level (child) list item */
}

ul#mylist li li li {
  /* Your style here for the third-level (grandchild) list item */
}
</style>

So this way you could simply give your main list an ID of "mylist" and each level could have different formatting for the elements without having to code in different styles in your nested foreach loops. This is obviously only useful to style list items differently up to 3 levels deep though - I suspect that anything from the fourth level onwards would just inherit that last style above.

Of course, this probably isn't much use to you as your situation seems to have a lot of different things being output at different levels - different siuze titles and different class names - but I thought I'd post it anyway :)

Link to comment
Share on other sites

@martin and @pete: just a quick explanation: '>' as a character means child element, while only chaining elements with space targets descendant elements.

  <div>
     <p.a>
     <div>
       <p.b>
     </div>
  </div>

In this case, div > p will select p.a only, while div p will target p.b as well as p.a.

Also, I noticed that my previous example was wrong, since the next-level li will never be direct descendant of the higher level li – there always'll be another ul wrapping the next level li's together. Will edit my post accordingly – it won't be as nice, but still will allow you to write cleaner CSS.

Link to comment
Share on other sites

Just to update Pete's CSS–If you use following CSS:

ul#my-ul > li { }
ul#my-ul > li > ul > li { }
ul#my-ul > li > ul > li > ul > li { }

You won't have to create the CSS for the deeper levels overriding the shallower ones :)

This is a nice technique that can be used, but isn't really using the cascading power of css when you need to redefine the different levels. In case of nested ul's it is easy to use inheritance if done right, no need to overwrite a lot anyway. Depends a lot what type of list you're trying to archive.

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...