pdoMenu - Using different

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.

1 Like

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:
image

The LIs at different levels get different markup :+1:

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>
1 Like

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.

1 Like

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}
1 Like

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.

1 Like

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