Skip to main content

This site requires you to update your browser. Your browsing experience maybe affected by not having the most up to date version.

General Questions /

General questions about getting started with SilverStripe that don't fit in any of the categories above.

Moderators: martimiz, Sean, biapar, Willr, Ingo, swaiba, simon_w

Getting all children and subchildren .. lots of levels deep?


Reply


8 Posts   2639 Views

Avatar
imagic

Community Member, 12 Posts

21 July 2011 at 10:28am

Hi guys, I've tried doing a search for this, but couldn't really find what I was after.

Basically I am making a problem solver page, where users are asked questions and depending on the answer,
they are asked a different question.

So I've set up a few questions as a pages and subpages.. (the screenshot will help you understand)

Now that's all fine, but the problem comes when displaying all these children and subchildren on the page.

They way I'm doing it now is shown below, but this seems like a super code heavy way of doing it.. Just wonder if there was an easier
way to get all children and subchildren of a page without having to next 10 children controls..

Can anyone please help? that would be awesome

<% control Children %>
<li class="answer"><a href="#" class="q1" rel="$Tag">$Title</a><ul>
<% control Children %>
       <li>$Title
   <ul>
<% control Children %>
<li class="answer"><a href="#" class="q2" rel="$Tag">$Title</a>
<ul>
<% control Children %>
<li>$Title<ul>
      <% control Children %>
<li class="answer"><a href="#" class="q3" rel="$Tag">$Title</a>
</li>
<% end_control %>
</ul>
</li>
<% end_control %>
</ul>
</li>
<% end_control %>
</ul>
</li>
<% end_control %>
</ul>
</li>
<% end_control %>

Avatar
swaiba

Forum Moderator, 1805 Posts

21 July 2011 at 9:50pm

hmmm

My first guess would be to only render the first question (possibly the first answers too) and then, depending on what is clicked, do ajax to add the info in. This would avoid having to render the whole tree first and I'd imagine it would be fairly straight forward. Best of luck...

Avatar
Willr

Forum Moderator, 5513 Posts

22 July 2011 at 8:19pm

I think in 2.4 it supports nested includes so you may be able to use recursion like below, otherwise you'll have to use PHP.

// includes/menu.ss

<% if Children %>
<% control Children %>
<a href="$Link">$MenuTitle</a>
<% include Menu %>
<% end_control %>
<% end_if %>

Avatar
martimiz

Forum Moderator, 1132 Posts

22 July 2011 at 10:56pm

I always thought you couldn't use templates recursively, so I tried to see if I missed it somehow. What I get is a timeout once I try to ?flush=1. So probably it wants to over and over add the same template to the manifest? (v2.4.5).

But I'd be happy if I were wrong... :-)

Avatar
martimiz

Forum Moderator, 1132 Posts

23 July 2011 at 12:58am

Edited: 23/07/2011 1:07am

OK: recursion is great for getting down the tree. Getting up to rootlevel looks somewhat like using breadcrumbs breadcrumbs, I guess. So maybe something like this:

// gets parent object into a DataObjectSet, root first
public function getParentList($maxDepth = 20) {

   $parentList = new DataObjectSet();
   $depth = 1;
   $currentpage = $this;

   while ($currentpage && $currentpage->ParentID && $depth < $maxDepth) {

      $parent = $currentpage->Parent();
      if (isset($parent->ID)) {
         $parentList->insertFirst($parent);
         $currentpage = $parent;
         $depth++;
      }
      else $currentpage = false;
   }
   return $parentList;
}

And then (here I put everything in one ul, where only the currentpage has no link, but you could do whatever you want with it):

<ul>
   <% control ParentList %>
      <li class="parent{$Pos}"><a href="$Link">$Title.XML</a></li>
   <% end_control %>

   <li class="currentPage">(current page) $Title.XML</li>

   <% if Children %>
      <% control Children %>
         <li class="newSelection"><a href="$Link">(possible new selection) $Title.XML</a></li>
      <% end_control %>
   <% end_if %>
</ul>

Maybe this will help some? [edit: use insertFirst instead of push]

Avatar
imagic

Community Member, 12 Posts

26 July 2011 at 2:35pm

Thanks for your reply guys, I've tried to use Willr's solution, but I get a timeout after doing a ?flush=1

Any ideas?

Also thanks martimiz for this bit of code, but I'm trying to go down the tree, rather than up:)

Avatar
martimiz

Forum Moderator, 1132 Posts

26 July 2011 at 11:41pm

Edited: 26/07/2011 11:59pm

There's always that bit about getting up or down that tree :-)

But I'm a bit confused now, since what my example does is get you exactly what your screenshot shows: when you're on page 'is this a thisle?' It shows you:

- first: all parent pages in the right order (as links)
- next: the page you're on now (not as link)
- finally: the childpages you can now choose from (as links)

As for that time-out - I mentioned that in my first reply...

[EDIT] ok - i see: not exactly: (if) you really want the entire tree in there - that could use some recursion...

Avatar
Tuckie

Community Member, 10 Posts

27 July 2011 at 7:12am

here's some code used to get all children, but it just returns a flat list, some tweaking should get you what you want:

function getAllChildren($objectType = null, $parentObject = null, $dataSet = null) {
      if ($parentObject == null) {
         return null;
      }
      
      //for first iteration
      if ($dataSet == null) {
         $dataSet = new DataObjectSet();
      }
      
      $children = $parentObject->Children();
      if (!empty($children)) {
         $dataSet->merge($children);
         foreach ($children as $child) {
               $dataSet = $this->getAllChildren($objectType, $child, $dataSet);
         }
      }
      
      //remove other object types if objectType has been specified
      if ($objectType) {
         foreach ($dataSet as $object) {
            if ($object->class != $objectType) {
               $dataSet->remove($object);
            }
         }
      }
      return $dataSet;
   }