Smirftsch Posted January 24, 2021 Share Posted January 24, 2021 Ok, I am absolutely sure I am missing something simple again, I also read a few more or less similar topics here, yet I couldn't find an answer. I am using pretty much the original function renderNavTree: function renderNavTree($items, $maxDepth = 0, $fieldNames = '', $class = 'nav') { // if we were given a single Page rather than a group of them, we'll pretend they // gave us a group of them (a group/array of 1) if($items instanceof Page) $items = array($items); // $out is where we store the markup we are creating in this function $out = ''; // cycle through all the items foreach($items as $item) { $pageid = wire('page')->id; // markup for the list item... // if current item is the same as the page being viewed, add a "current" class to it $out .= $item->id == wire('page')->id ? "<li class='current'>" : "<li>"; // markup for the link $out .= "<a href='$item->url'>$item->title.$item->id.$pageid</a> "; // if there are extra field names specified, render markup for each one in a <div> // having a class name the same as the field name if($fieldNames) foreach(explode(' ', $fieldNames) as $fieldName) { $value = $item->get($fieldName); if($value) $out .= " <div class='$fieldName'>$value</div>"; } // if the item has children and we're allowed to output tree navigation (maxDepth) // then call this same function again for the item's children if($item->hasChildren() && $maxDepth ) { if($class == 'nav') $class = 'nav nav-tree'; if ($maxDepth > 1 || $item->id == wire('page')->id) $out .= renderNavTree($item->children, $maxDepth-1, $fieldNames, $class); else { foreach($item->children as $childitem) { if ($childitem->id == wire('page')->id) $out .= renderNavTree($item->children, $maxDepth-1, $fieldNames, $class); } } } // close the list item $out .= "</li>"; } // if output was generated above, wrap it in a <ul> if($out) $out = "<ul class='$class'>$out</ul>\n"; // return the markup we generated above return $out; } but I want it only to render the children of the selected page. Right now the output is like that (having lets say "child2 of child1 selected): Parent Page Parent child 1 child of child 1 child2 of child 1 child of child2 Fine so far and looks as wanted- BUT - problem appears if having more than one child of parent- it looks like this: Parent child 1 child of child 1 child2 of child 1 child of child2 of child 1 child 2 child of child2 child2 of child2 while I only would want it to render the tree of child 1, not of child2. Since all are children of Parent (hence same wire('page')->id), I can't distinguish it with id, but what else can I do here? Ok, I realized that this question is maybe confusing, what I wanted to archive is that only the navtree of the selected page is being rendered, nothing else (well if being absolutely perfect maybe 1 level of rootParent also). Link to comment Share on other sites More sharing options...
Smirftsch Posted January 25, 2021 Author Share Posted January 25, 2021 for anyone digging such a thing, I mostly solved it now by using "renderNavTree($page.." instead of "renderNavTree($page->rootParent..." in basic-page and using parents() additionally: // cycle through all the items foreach($items as $item) { if (renderParent && $item->id == wire('page')->id) { $SkipLevel = 1; // Skip homepageroot foreach($item->parents() as $pitem) { if ($SkipLevel) { $SkipLevel--; continue; } $out .="<ul><li class='parentnav'><a href='$pitem->url'>$pitem->title</a></li>"; } $out .="<ul>"; } ... only need to make it render 1st level of parentRoot yet ? Link to comment Share on other sites More sharing options...
BillH Posted January 25, 2021 Share Posted January 25, 2021 If you haven't discovered it already, the parent() function (https://processwire.com/api/ref/page/parent/) used with a selector can be useful for checking if a page has a particular parent - at any level, not just a parent immediately above it. It returns a null page (id = 0) if the page doesn't have a parent that matches the selector. For example, if you want to check if a page is a child of a page with id = 123: if ($page->parent("id=123")->id != 0) {... With other functions, the has_parent selector can be used for similar purposes. Link to comment Share on other sites More sharing options...
Smirftsch Posted January 26, 2021 Author Share Posted January 26, 2021 Thanks! I have to admit I am still a little confused with all options and especially selectors. I tried through a lot of things to get the working of all of it. Link to comment Share on other sites More sharing options...
wishbone Posted June 27, 2021 Share Posted June 27, 2021 On 1/24/2021 at 11:03 AM, Smirftsch said: // if the item has children and we're allowed to output tree navigation (maxDepth) // then call this same function again for the item's children if($item->hasChildren() && $maxDepth ) { if($class == 'nav') $class = 'nav nav-tree'; if ($maxDepth > 1 || $item->id == wire('page')->id) $out .= renderNavTree($item->children, $maxDepth-1, $fieldNames, $class); else { foreach($item->children as $childitem) { if ($childitem->id == wire('page')->id) $out .= renderNavTree($item->children, $maxDepth-1, $fieldNames, $class); } } } Same problem here: render submenus only for the current page. Instead of Smirftsch's above, I tried the following (I have a non-$out-versionn of the RenderNavTree): // if the item has children and we're allowed to output tree navigation (maxDepth) // then call this same function again for the item's children $currentItem = $item->id == wire('page')->id; if(($item == $currentItem and $item->hasChildren())) { renderNavTree($item->children); and I call the function like so: <aside id='sidebar'><?php // rootParent is the parent page closest to the homepage // you can think of this as the "section" that the user is in // so we'll assign it to a $section variable for clarity // instead of $section, render the whole tree, beginning from the homepage $home = $pages->get('/'); // if there's more than 1 page in this section... if($home->hasChildren > 1) { // output sidebar navigation // see _init.php for the renderNavTree function renderNavTree($home, $maxDepth = 2); } // output sidebar text if the page has it echo $page->sidebar; ?></aside><!-- end sidebar --> only renders "Home" ? (I'm a non-coder anyway...) Link to comment Share on other sites More sharing options...
wishbone Posted June 30, 2021 Share Posted June 30, 2021 found the code! In a post from 2011 ? thx to @BDH Does exactly what I want: show the whole tree, but only render submenus of a current item. Could have achieved that with css also, but semantically, not that clean. Now I tried to prepend the homepage like this (before the "foreach"), but doesn't work: $rootPage->children->prepend($rootpage); What am I doing wrong? Anyway, I don't understand the $s=str_replace thing - works, but as I'm trying to learn from examples, would be nice to understand what that is. There are still two modules: MarkupMenu and Menu Builder - but they seem to be overloaded for this simple task? 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