pdoMenu - Using different

I think this is the way to go. I forgot there is now a level placeholder, it’s fairly new and doesn’t seem to be documented. @halftrainedharry is always good at looking under the hood!

1 Like

Hey dejaya…it’s my desired layout.

Do I do the level inside an id? Like you provided above? Is it possible to do that? I tried it and my nav had an error

[[+id:isnot=`8`

:then=`

	[[- Your default LI and associated markup for non-Competition pages ]]
	<li class="menu-item [[+classnames]]"><a class="menu-link" href="[[+link]]" [[+attributes]]><div>[[+menutitle]]</div></a>[[+wrapper]]</li>

`:else=`

	[[+level:is=`1`:then=`
		[[- Your Level 1 LI and associated markup ]]
		<li class="menu-item mega-menu [[+classnames]]"><a class="menu-link" href="[[+link]]" [[+attributes]]><div>[[+menutitle]]</div></a>[[+wrapper]]</li>
	`]]


	[[+level:is=`2`:then=`
		[[- Your Level 2 LI and associated markup ]]
		<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=`
		[[- Your Level 3 LI and associated markup ]]
		<li class="menu-item [[+classnames]]"><a class="menu-link" href="[[+link]]" [[+attributes]]><div>[[+menutitle]]</div></a>[[+wrapper]]</li>
	`]]


	[[+level:is=`4`:then=`
		[[- Your Level 4 LI and associated markup ]]
		<li class="menu-item [[+classnames]]"><a class="menu-link" href="[[+link]]" [[+attributes]]><div>[[+menutitle]]</div></a>[[+wrapper]]</li>
	`]]


`]]

Hey @coconghaile

It definitely should be possible - my code was just an untested example really but it should be achievable.

What error do you see?

It is showing the [[+id:isnot=8:then= in the actual navigation bar.

That, I think, will be due to a bug in the 3.x MODX parser.

@halftrainedharry has posted a fix for that issue here.

However, even after applying that fix, I still see [what I think are] MODX tag parsing issues when adding output modifiers to the template chunks.

I still think it should be possible with pdoMenu but have hit a wall for now.

BTW - from my previous code …

[[+id:isnot=`8`

… isn’t quite right as we should be checking against the top-level parent of the current ID - not the ID itself.

Not sure I’ve helped much, sorry!

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?