Smirftsch Posted January 24, 2021 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).
Smirftsch Posted January 25, 2021 Author 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 ?
BillH Posted January 25, 2021 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.
Smirftsch Posted January 26, 2021 Author 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.
wishbone Posted June 27, 2021 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...)
wishbone Posted June 30, 2021 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?
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