BoldMinded acquires Ansel, support ending for all add-ons. BoldMinded acquires Ansel, support ending for all add-ons. Read More →
Support has been discontinued. Issues remain available as an archive. Support has been discontinued. Issues remain available as an archive.
Getting the node ID for a parent of a parent...
#185 opened by SanctusMediaLtd
Description
I have a menu structure that's 3 levels deep. When showing something on the third level, I want a menu that shows everything on the second level inclusive – but NOT the very top level of the entire menu.
From the docs, there doesn't seem to be an easy way of doing this? Or am I missing something?
O.
Replies
- TJ Draper
Replied 8/13/2020 10:15 AM, Edited 8/13/2020 11:50 AM
If you want everything on level 2, you could do something like this:
{exp:construct:nodes tree_id="SOME_ID" parent_id="SOME_PARENT_ID"} {!-- Template Code Here --} {/exp:construct:nodes}
But I may be misunderstanding what you're trying to do.
- SanctusMediaLtd
Replied 8/13/2020 10:21 AM, Edited 8/13/2020 11:50 AM
I can't hardcode the parent_id because its a single template.
Essentially, when a user clicks from the level 1 (the site's top menubar), I'm showing everything under that top level parent in a side bar navigation. For level 2 items, parent_id='{construct_route:node_parent_id}' works fine because the parent node happens to be the level 1 node.
When I click a level 3 node, I only see the level 3 nodes in the right-hand bar, because the parent node of level 3 is on level 2. I need to see levels 2 and 3 in that sidebar, regardless of which level the active node is in...
I hope that makes sense.
O.
- SanctusMediaLtd
Replied 8/13/2020 10:24 AM, Edited 8/13/2020 11:50 AM
(In other words, I need the level 1 parent ID, regardless of how many levels down I am, for the current node)
- TJ Draper
Replied 8/13/2020 10:39 AM, Edited 8/13/2020 11:50 AM
Can you utilize the
node_slug
from a segment? - SanctusMediaLtd
Replied 8/13/2020 10:46 AM, Edited 8/13/2020 11:50 AM
I'm not sure how
node_slug
would help me :Shere's what I have:
{exp:construct:nodes tree_id="1" parent_id="{construct_route:node_parent_id}" } {if construct:level_count == 1} <ul class="pager"> {/if} <li class="{if construct_route:node_id == construct:node_id}active{/if}"><a href="/{construct:node_full_route}">{construct:node_name}</a></li> {if construct:has_children} <ul class="kids"> {/if} {construct:children} {if construct:has_children} </ul> {/if} {if construct:level_count == construct:level_total_results} </ul> {/if} {/exp:construct:nodes}
So
parent_id
param almost needs atop_level_parent_id
of sorts to make sure I always maintain the view of levels 2, 3, and beyond? - SanctusMediaLtd
Replied 8/13/2020 10:46 AM, Edited 8/13/2020 11:50 AM
Apologies for that last comment. Markdown not working as expected:
{exp:construct:nodes tree_id="1" parent_id="{construct_route:node_parent_id}"} {if construct:level_count == 1} <ul class="pager"> {/if} <li class="{if construct_route:node_id == construct:node_id}active{/if}"><a href="/{construct:node_full_route}">{construct:node_name}</a></li> {if construct:has_children} <ul class="kids"> {/if} {construct:children} {if construct:has_children} </ul> {/if} {if construct:level_count == construct:level_total_results} </ul> {/if} {/exp:construct:nodes}
- TJ Draper
Replied 8/13/2020 10:55 AM, Edited 8/13/2020 11:50 AM
If you have access to the node slug of the parent in the URL, you could do something like this:
{exp:construct:nodes tree_id="1" node_slug="{segment_x}"} {if construct:node_level > 1} {if construct:level_count == 1} <ul class="pager"> {/if} <li class="{if construct_route:node_id == construct:node_id}active{/if}"> <a href="/{construct:node_full_route}">{construct:node_name}</a></li> {if construct:has_children} <ul class="kids"> {construct:children} </ul> {/if} </li> {if construct:level_count == construct:level_total_results} </ul> {/if} {/if} {/exp:construct:nodes}
- SanctusMediaLtd
Replied 8/13/2020 10:59 AM, Edited 8/13/2020 11:50 AM
I'm sorry, but nowhere in your response – or your documentation - have you explained what the
node_slug
parameter actually does...?Unfortunately though, it returns absolutely nothing in the format you've suggested.
- TJ Draper
Replied 8/13/2020 11:09 AM, Edited 8/13/2020 11:50 AM
> Unfortunately though, it returns absolutely nothing in the format you’ve suggested.
Can you elaborate? I'm happy to help if I can but I don't know what "nothing in the format you’ve suggested" means. Does it mean that the tag is not outputting anything?
I realize the documentation could be more clear on node_slug. I'm sorry about that. It retrieves a node based on slug. So if you have the path to your level 3 node in the URL, one of those segments should be the slug. It's been a while since I've been in the code, it's possible that it won't retrieve children, might have to experiment a little. If it doesn't retrieve children, you could use a embed template to pass in the that ID to another construct tag in that embed.
So since in my example I did
{if construct:node_level > 1}
, if you're not seeing any output from that tag, that may be why. - SanctusMediaLtd
Replied 8/13/2020 11:24 AM, Edited 8/13/2020 11:50 AM
Yes; I mean the tag returns nothing when the code is used in the way you've shown.
> It retrieves a node based on slug. So if you have the path to your level 3 node in the URL, one of those segments should be the slug.
I'm not sure I understand. Are you saying that if I pass in {segment_1} into the node parameter, it would use that as the "starting point"?
I've tried applying your code verbatim, using segments 1 and 2 (and 3) on both level 2 and level 3 pages and the tag still has no output.
I've tried applying the
node_slug
parameter to my existing tags, and that also doesn't work.It would seem we've maybe reached an impasse, as I thought this would maybe be "out-of-the-box" functionality.
- TJ Draper
Replied 8/13/2020 11:31 AM, Edited 8/13/2020 11:50 AM
There's no doubt that this is missing functionality and I'm taking notes for what can be added in the next major version. That said, I have no doubt that what you're trying to do is possible with a little templating.
Passing a segment into the
node_slug
parameter will retrieve a node based on the segment. Which is why, if the top level node's slug is in the URL, it could be useful. As I mentioned, my memory is unclear on whether it also will retrieve that node's children for output (and I'm not able to dig into that code or replicate a test situation right at this moment). If it doesn't retrieve the children, it may explain why my sample code is not producing any output since I had a conditional in there to limit to level 2 or higher.I understand though if you don't want to pursue this further.
If you do want to pursue it, I would suggest maybe taking everything out from inside of the tag in my sample code and just outputting the node name to see if it's getting anything at all.
- SanctusMediaLtd
Replied 8/13/2020 11:38 AM, Edited 8/13/2020 11:50 AM
Understood. I tried just running a simple loop (moving the UL element to the outside)...
{exp:construct:nodes tree_id="1" node_slug="{segment_1}"} <li class="{if construct_route:node_id == construct:node_id}active{/if}"> <a href="/{construct:node_full_route}">{construct:node_name}</a></li> {if construct:has_children} <ul class="kids"> {construct:children} </ul> {/if} </li> {/exp:construct:nodes}
... that returns just the node specified by
node_slug
and nothing else; no children, as you thought might be the case.Embeds will put additional load on every page, which I'd rather avoid.
I'm sorry to say I think we'll need to rip out Construct and put in NavEE, which can do what I need it to, in the timeframe we have remaining :( (We tried Construct because your UI is much cleaner and easier for our clients)
For your own R&D, they have a
start_nav_from_parent
parameter, with a few related parameters to set the starting point and show as much or as little of the sub-navigation as required. Additionally, allowing Construct to 'read' the URL to see if it matches a manually entered URL would be good (again, NavEE can do this) rather than every EE template having to be in a Construct template.Thanks nonetheless for your help.
- TJ Draper
Replied 8/13/2020 11:50 AM
Understood. I'm sorry about that.
The only comment I'll offer — and I'm not suggesting you should reconsider, because I totally understand where you're coming from and it doesn't solve the root (heh) of the problem — is this: As someone who's spent a lot of time with EE from a performance perspective, and has helped rescue poorly performing EE sites and presented at conferences on the topic, the load increase from embeds has been severely overstated. The reason they've gotten a bad rap, and what led people to start thinking they were just bad and should not be used is because of what they enable. It's possible to compound tag loops that produce an unseemly amount of heavy queries, which can really bog down page load performance. As an example, let's say you have a channel entries tag that has a limit of 20. Then you put an embed in that loop. That embed has a channel entries tag with a limit of 20. You've just compounded your queries by a large amount. You can see where this gets out of hand. That's where embeds got a bad rap. As far as the burden of an embed, of course there is some, but it's not much by itself. It's barely noticeable, in fact. If you had embeds of just HTML, you'd have to have literally hundreds of embeds before you noticed a speed slowdown.
But, like I said, that doesn't solve the real problem here, which is the deficiency of ways to get nodes in Construct and the potential unwieldiness of wrangling multiple templates just for the correct output of Construct's tags.