I did this change and it fixed some of it but having another issue now. It’s showing the end tags ]] now.
It’s strange because when I used
[[+id:is='8':then='menu-item mega-menu':else='menu-item']]
I had no issue but when I try to have one inside the other
[[+id:is='8':then='[[+level:is='1':then='level1-class']][[+level:is='2':then='level2-class']]':else='menu-item']]
that’s when I get the error.
I’m seeing similar unpredictable behaviour with nested output modifier calls.
Will try to pin it down - it may be that the bug goes beyond the fix that @halftrainedharry supplied - or it may be specific to pdoMenu.
I take it you’re using backticks in your code, rather than the single quotes?
I am indeed. Just had to change them here to see the code properly.
To preserve the backticks in your code, either put lines with three back-ticks at the start and at the end of your code
```//line with 3 back-ticks at the beginning
//your code here
```//line with 3 back-ticks at the end
or add double-backticks (``
) right before and after your code (if your code contains single backticks (`
).
I don’t think this is the case. A simple nested output modifier shouldn’t cause any problem.
- What version of MODX are you using?
- What version of pdoTools are you using?
- What is your current pdoMenu-call and the content of the template-chunk?
Thanks Harry, I’m keen to get my head around pdoMenu - especially for more complex menus like the one @coconghaile is working on - so I’ve kind of joined him on this journey.
For me,
MODX 3.0.1-pl
pdoTools 3.0.0-pl
I’ve stripped this back a bit to try and find where the problem is … so - pdoMenu call:
[[pdoMenu?
&parents=`0`
&level=`0`
&tplOuter=`tplOuter`
&tpl=`tplRow`
]]
tplRow is designed to allow different markup for LIs at different levels:
[[+level:is=`1`:then=`
<li class="menu-item [[+classnames]]"><a class="menu-link" href="[[+link]]" [[+attributes]]><div>[[+menutitle]]</div></a>[[+wrapper]]</li>
`]]
[[+level:is=`2`:then=`
<li class="menu-item mega-menu-title mega-menu-column [[+classnames]]"><a class="menu-link" href="[[+link]]" [[+attributes]]><div>[[+menutitle]]</div></a>[[+wrapper]]</li>
`]]
[[+level:is=`3`:then=`
<li class="menu-item [[+classnames]]"><a class="menu-link" href="[[+link]]" [[+attributes]]><div>[[+menutitle]]</div></a>[[+wrapper]]</li>
`]]
[[+level:is=`4`:then=`
<li class="menu-item [[+classnames]]"><a class="menu-link" href="[[+link]]" [[+attributes]]><div>[[+menutitle]]</div></a>[[+wrapper]]</li>
`]]
tplOuter
is where the problems begin for me. If we go with the following:
<ul class="menu-container [[+classnames]]">[[+wrapper]]</ul>
… we get a good starting point:
The LIs at different levels get different markup
Now to specify different markup for ULs at different levels in a similar way in tplOuter:
[[+level:is=`1`:then=`
<ul class="menu-container [[+classnames]]">[[+wrapper]]</ul>
`]]
[[+level:is=`2`:then=`
<ul class="row list-unstyled [[+classnames]]">[[+wrapper]]</ul>
`]]
[[+level:is=`3`:then=`
<ul class="sub-menu-container [[+classnames]]">[[+wrapper]]</ul>
`]]
[[+level:is=`4`:then=`
<ul class="sub-menu-container mega-menu-dropdown [[+classnames]]">[[+wrapper]]</ul>
`]]
This results in the menu disappearing altogether.
So let’s simplify it a bit, tplOuter:
[[+level:is=`1`:then=`*LEVEL 1 UL*`]]
<ul class="sub-menu-container [[+classnames]]">[[+wrapper]]</ul>
Yep, that works:
So let’s just move the UL markup into the output modifier:
[[+level:is=`1`:then=`<ul class="sub-menu-container [[+classnames]]">[[+wrapper]]</ul>`]]
Again, the menu disappears completely.
If I uncache the call:
[[!+level:is=`1`:then=`<ul class="sub-menu-container [[+classnames]]">[[+wrapper]]</ul>`]]
No menu is returned, just:
`]]
It seems that once the [[+wrapper]]
placeholder goes in the [[+level]] output modifier “then” response, it falls over.
This is true even if I simplify the tplRow
output to just a single plain LI:
<li class="menu-item [[+classnames]]"><a class="menu-link" href="[[+link]]" [[+attributes]]><div>[[+menutitle]]</div></a>[[+wrapper]]</li>
I also tried switching all the modifier calls to IF snippets - the result was the same.
Sorry, that’s a lot!
Thanks as always.
Modx Version: 3.0.1-pl
pdoTools version: 3.0.0-pl
This is what I currently have in the pdoMenu call:
[[pdoMenu?
&parents=`0`
&level=`0`
&tplOuter=`outerTpl`
&tplInner=`subMenuContainerTpl`
&tpl=`navTpl`
]]
outerTpl code: <ul class="menu-container">[[+wrapper]]</ul>
subMenuContainerTpl code below:
[[+id:isnot=`8`:then=`<ul class="sub-menu-container">[[+wrapper]]</ul>`
:else=`
[[+level:is=`1`:then=`
<div class="mega-menu-content mega-menu-style-2"><div class="container"><ul class="row list-unstyled">[[+wrapper]]</ul></div></div>
`]]
[[+level:is=`2`:then=`
<ul class="sub-menu-container">[[+wrapper]]</ul>
`]]
[[+level:is=`3`:then=`
<ul class="sub-menu-container mega-menu-dropdown">[[+wrapper]]</ul>
`]]
`]]
navTpl code below:
[[+id:isnot=`8`:then=`<li class="menu-item"><a class="menu-link" href="[[+link]]" [[+attributes]]><div>[[+menutitle]]</div></a>[[+wrapper]]</li>`
:else=`
[[+level:is=`1`:then=`
<li class="menu-item mega-menu"><a class="menu-link" href="[[+link]]" [[+attributes]]><div>[[+menutitle]]</div></a>[[+wrapper]]</li>
`]]
[[+level:is=`2`:then=`
<li class="menu-item mega-menu-title mega-menu-column"><a class="menu-link" href="[[+link]]" [[+attributes]]><div>[[+menutitle]]</div></a>[[+wrapper]]</li>
`]]
[[+level:is=`3`:then=`
<li class="menu-item"><a class="menu-link" href="[[+link]]" [[+attributes]]><div>[[+menutitle]]</div></a>[[+wrapper]]</li>
`]]
[[+level:is=`4`:then=`
<li class="menu-item"><a class="menu-link" href="[[+link]]" [[+attributes]]><div>[[+menutitle]]</div></a>[[+wrapper]]</li>
`]]
`]]
This is how I want the code to turn out:
<ul class="menu-container">
<li class="menu-item"><a class="menu-link" href="#" ><div>Home</div></a></li>
<li class="menu-item"><a class="menu-link" href="#" ><div>Teams</div></a>
<ul class="sub-menu-container">
<li class="menu-item "><a class="menu-link" href="#" ><div>Team One</div></a></li>
<li class="menu-item "><a class="menu-link" href="#" ><div>Team Two</div></a></li>
</ul>
</li>
<li class="menu-item mega-menu"><a class="menu-link" href="#"><div>Competition</div></a>
<div class="mega-menu-content mega-menu-style-2">
<div class="container">
<ul class="row list-unstyled">
<li class="menu-item mega-menu-title mt-0 col-lg-3 mega-menu-column"><a class="menu-link" href="#"><div>National (6)</div></a>
<ul class="sub-menu-container">
<li class="menu-item"><a class="menu-link" href="#"><div>Semi-Final</div></a>
<ul class="sub-menu-container mega-menu-dropdown">
<li class="menu-item"><a class="menu-link" href="#"><div>Game 1</div></a></li>
<li class="menu-item"><a class="menu-link" href="#"><div>Game 2</div></a></li>
</ul>
</li>
<li class="menu-item"><a class="menu-link" href="#"><div>Final</div></a></li>
</ul>
</li>
<li class="menu-item mega-menu-title mt-0 col-lg-3 mega-menu-column"><a class="menu-link" href="#"><div>Dublin (7)</div></a>
<ul class="sub-menu-container">
<li class="menu-item"><a class="menu-link" href="#"><div>Semi-Final</div></a>
<ul class="sub-menu-container mega-menu-dropdown">
<li class="menu-item"><a class="menu-link" href="#"><div>Game 1</div></a></li>
<li class="menu-item"><a class="menu-link" href="#"><div>Game 2</div></a></li>
</ul>
</li>
<li class="menu-item"><a class="menu-link" href="#"><div>Final</div></a></li>
</ul>
</li>
<li class="menu-item mega-menu-title mt-0 col-lg-3 mega-menu-column"><a class="menu-link" href="#"><div>Kerry (8)</div></a>
<ul class="sub-menu-container">
<li class="menu-item"><a class="menu-link" href="#"><div>Semi-Final</div></a>
<ul class="sub-menu-container mega-menu-dropdown">
<li class="menu-item"><a class="menu-link" href="#"><div>Game 1</div></a></li>
<li class="menu-item"><a class="menu-link" href="#"><div>Game 2</div></a></li>
</ul>
</li>
<li class="menu-item"><a class="menu-link" href="#"><div>Final</div></a></li>
</ul>
</li>
<li class="menu-item mega-menu-title mt-0 col-lg-3 mega-menu-column"><a class="menu-link" href="#"><div>Galway (9)</div></a>
<ul class="sub-menu-container">
<li class="menu-item"><a class="menu-link" href="#"><div>Semi-Final</div></a>
<ul class="sub-menu-container mega-menu-dropdown">
<li class="menu-item"><a class="menu-link" href="#"><div>Game 1</div></a></li>
<li class="menu-item"><a class="menu-link" href="#"><div>Game 2</div></a></li>
</ul>
</li>
<li class="menu-item"><a class="menu-link" href="#"><div>Final</div></a></li>
</ul>
</li>
</ul>
</div>
</div>
</li>
</ul>
Here’s an image of the simple dropdown:
And here’s the Mega Menu:
I think the problem is that pdoTools doesn’t really “parse” the tplOuter/tplInner templates. Only simple placeholders are replaced.
Try changing parseChunk
to getChunk
in these two lines to see if that solves the issue.
Thanks Harry - that does indeed fix the issue for me👍
Does that represent an issue / bug / limitation in pdoTools? Will that change have any other impacts?
I guess ideally it’d be good to be able to create the menu with pdoTools as it comes out of the box - but I appreciate this may be the only way.
Very much appreciate your time again.
I think the real problem is line 113. (Tags that aren’t properly parsed on line 173 should get parsed eventually.)
So I think the solution (without changing the code), is to define both &tplOuter
and &tplInner
and only use output-modifiers in &tplInner
.
In &tplOuter
only use simple placeholder-tags!
Also, for this specific navigation, as one of the branches (Competition) is different than the rest, I would try using nested pdoMenu calls (as has been suggested before).
[[pdoMenu?
&parents=`0`
&level=`2`
&tpl=`tplRow`
]]
Then in the chunk tplRow if the ID is 3 (= Competition) make a new pdoMenu-call (with branch-specific templates) instead of outputting the wrapper.
<li[[+classes]]><a href="[[+link]]" [[+attributes]]>[[+menutitle]]</a>
[[+id:is=`3`:then=`[[pdoMenu?&parents=`3`&level=`0`&tpl=`tplCompetitionRow`]]`:else=`[[+wrapper]]`]]
</li>
Well, this doesn’t solve the issue properly.
So the best solution is probably to use Fenom-syntax in the templates. Something like:
{if $level == 1}
<ul class="level1-class">{$wrapper}</ul>
{elseif $level == 2}
<ul class="level2-class">{$wrapper}</ul>
{else}
<ul class="levelx-class">{$wrapper}</ul>
{/if}
This gets parsed properly.
Or use Wayfinder instead.
Another point is, that there is no [[+id]]
placeholder available in the tplOuter/tplInner templates.
Only these placeholders are set:
[[+wrapper]]
, [[+classes]]
, [[+classNames]]
, [[+classnames]]
, [[+level]]
[[+wf.wrapper]]
, [[+wf.classes]]
, [[+wf.classNames]]
, [[+wf.classnames]]
, [[+wf.level]]
So if you have to rely on the ID to determine the class of the <ul>
in the template, then maybe move the <ul>
to the &tpl
template instead.
Here is an example: The tplOuter template contains only the [[+wrapper]]
placeholder.
[[pdoMenu?
&parents=`0`
&level=`0`
&tplOuter=`@INLINE {{+wrapper}}`
&tpl=`navTpl`
]]
Chunk navTpl: (Assumes the page “Competition” has ID=3)
{set $parent_ids = $_modx->getParentIds($id)}
{if 3 in $parent_ids}
*** child of competition ***
{if $level == 1}
<li class="competition-level1"><a href="{$link}" {$attributes}>{$menutitle}</a>
{if $wrapper?}
<ul class="competition-level1">{$wrapper}</ul>
{/if}
</li>
{elseif $level == 2}
<li class="competition-level2"><a href="{$link}" {$attributes}>{$menutitle}</a>
{if $wrapper?}
<ul class="competition-level2">{$wrapper}</ul>
{/if}
</li>
{elseif $level == 3}
<li class="competition-level3"><a href="{$link}" {$attributes}>{$menutitle}</a>
{if $wrapper?}
<ul class="competition-level3">{$wrapper}</ul>
{/if}
</li>
{else}
<li class="competition-level4"><a href="{$link}" {$attributes}>{$menutitle}</a>
{if $wrapper?}
<ul class="competition-level4">{$wrapper}</ul>
{/if}
</li>
{/if}
{elseif $id == 3}
*** COMPETITION ***
<li class="competition"><a href="{$link}" {$attributes}>{$menutitle}</a>
{if $wrapper?}
<ul class="competition">{$wrapper}</ul>
{/if}
</li>
{else}
+++ other branch +++
{if $level == 1}
<li class="level1"><a href="{$link}" {$attributes}>{$menutitle}</a>
{if $wrapper?}
<ul class="level1">{$wrapper}</ul>
{/if}
</li>
{elseif $level == 2}
<li class="level2"><a href="{$link}" {$attributes}>{$menutitle}</a>
{if $wrapper?}
<ul class="level2">{$wrapper}</ul>
{/if}
</li>
{else}
<li class="level3"><a href="{$link}" {$attributes}>{$menutitle}</a>
{if $wrapper?}
<ul class="level3">{$wrapper}</ul>
{/if}
</li>
{/if}
{/if}
An <ul>
is output, if the placeholder [[+wrapper]]
is not empty.
{if $wrapper?}
<ul class="level3">{$wrapper}</ul>
{/if}
Thanks Harry - I’m glad at least that you came across the same issues I did!
I must admit I’ve never seen the Fenom syntax before. I take it that’s only available within a pdoTools call?
That said, I feel it might be time to surrender to the nested pdoMenu calls as suggested by @lucy and yourself …
Thanks a million for all your help guys. I’m gonna crack away with this now to see.
This is another question I was gonna ask…Wayfinder should be fine?
Fenom is very popular in the russian-speaking MODX community. It gets installed with pdoTools but can also be used for the rest of the site (setting pdotools_fenom_parser
).
That is one possibility. Another is to use the code I posted above where $_modx->getParentIds($id)
is used to determine if the current resource is in the “Competition” branch or not. Just replace the markup in the example with the correct one.
I haven’t tested it, but it looks like Wayfinder has the same problem, where tplOuter/tplInner aren’t parsed and only simple placeholders are replaced. There is also no placeholder [[+id]]
and even no placeholder [[+level]]
in tplOuter/tplInner in Wayfinder.
So stay with pdoMenu and just embrace Fenom.
I forgot to reply earlier saying that this works an absolute treat now. Thanks a million for all your help guys. I really appreciate it. I’ll add the code that works for me.
Here’s the pdoMenu call
<nav class="primary-menu">
<ul class="menu-container">
[[pdoMenu?
&parents=`0`
&level=`0`
&tplOuter=`@INLINE {{+wrapper}}`
&tpl=`navTpl`
]]
</ul>
</nav>
Here’s the navTpl call
{set $parent_ids = $_modx->getParentIds($id)}
{if 8 in $parent_ids}
{if $level == 1}
<li class="menu-item mega-menu"><a class="menu-link" href="{$link}" {$attributes}>{$menutitle}</a>
{if $wrapper?}
<div class="mega-menu-content mega-menu-style-2"><div class="container"><ul class="row list-unstyled">{$wrapper}</ul></div></div>
{/if}
</li>
{elseif $level == 2}
<li class="menu-item mega-menu-title mt-0 col-lg-3 mega-menu-column"><a class="menu-link" href="{$link}" {$attributes}>{$menutitle}</a>
{if $wrapper?}
<ul class="sub-menu-container">{$wrapper}</ul>
{/if}
</li>
{elseif $level == 3}
<li class="menu-item"><a class="menu-link" href="{$link}" {$attributes}>{$menutitle}</a>
{if $wrapper?}
<ul class="sub-menu-container mega-menu-dropdown">{$wrapper}</ul>
{/if}
</li>
{else}
<li class="menu-item"><a class="menu-link" href="{$link}" {$attributes}>{$menutitle}</a>
{if $wrapper?}
<ul class="sub-menu-container mega-menu-dropdown">{$wrapper}</ul>
{/if}
</li>
{/if}
{elseif $id == 8}
<li class="menu-item mega-menu"><a class="menu-link" href="{$link}" {$attributes}>{$menutitle}</a>
{if $wrapper?}
<div class="mega-menu-content mega-menu-style-2"><div class="container"><ul class="row list-unstyled">{$wrapper}</ul></div></div>
{/if}
</li>
{else}
{if $level == 1}
<li class="menu-item"><a class="menu-link" href="{$link}" {$attributes}>{$menutitle}</a>
{if $wrapper?}
<ul class="sub-menu-container">{$wrapper}</ul>
{/if}
</li>
{elseif $level == 2}
<li class="menu-item"><a class="menu-link" href="{$link}" {$attributes}>{$menutitle}</a>
{if $wrapper?}
<ul class="sub-menu-container">{$wrapper}</ul>
{/if}
</li>
{else}
<li class="menu-item"><a class="menu-link" href="{$link}" {$attributes}>{$menutitle}</a>
{if $wrapper?}
<ul class="sub-menu-container">{$wrapper}</ul>
{/if}
</li>
{/if}
{/if}
Like I said…this works perfectly for me.
NB: Would anyone know how to add a CURRENT class. So when you are on the current page, it’d add the current class to the class tags.
Does anyone know, when I add the tag &resources to the pdoMenu call, how do you get it to include the child pages. So when I add the call below, it only shows those resources and not the child pages under those resources.
<nav class="primary-menu">
<ul class="menu-container">
[[pdoMenu?
&parents=`0`
&level=`0`
&resources=`2,3,4,7,9`
&tplOuter=`@INLINE {{+wrapper}}`
&tpl=`navTpl`
]]
</ul>
</nav>
Use the placeholder {$classnames}
in the template. By default it adds the class “active”, but you can change that with the property &hereClass
.
List the IDs in the &parents
property and not in the &resources
property.
Thanks a million. Appreciate all your help.
This doesn’t list the parent. It only shows in child inside the parent ID
I want to show the parent and the child for certain parent ID’s