pdoMenu multilevel parent selection including weblinks

I’m currently working on a multilevel (currently 3) menu, where all the sublevels are each hidden in a dropdown by default. On click on a dropdown parent, the next level should expands and so on. Now the navigation should obviously stay expanded to show the currently active site. Right now it works if I select Sub-Sub-Entry 1 that the navigation stays expanded like I want it to:

* Entry 1 +               // expanded
   * Sub-Entry 1 +        // expanded
      * Sub-Sub-Entry 1   <-- selected active site
      * Sub-Sub-Entry 2
      * Sub-Sub-Entry 3

However when I select Sub-Sub-Entry 2 I only get:

* Entry 1 +               // expanded
   * Sub-Entry 1 +        // closed!

I would’ve thought that the &tplParentRowActive would also work on the Sub-Sub-Entry 2 as I consider the Sub-Entry 1 is it’s parent, but it doesn’t work. Any ideas where I went wrong?
Here is my pdoMenu call:

[[pdoMenu?
  &parents=`0`
  &level=`3`
  &tpl=`@INLINE <li><a href="[[+link]]" [[+attributes]]>[[+menutitle]]</a>[[+wrapper]]</li>`
  &tplHere=`@INLINE <li><a href="[[+link]]" [[+classes]] [[+attributes]]>[[+menutitle]]</a>[[+wrapper]]</li>`
  &tplParentRow=`@INLINE <li><span [[+classes]]>[[+menutitle]]</span>[[+wrapper]]</li>`

  &tplParentRowActive=`@INLINE <li><span class="[[+level:gt=`1`:then=`opener2`:else=`opener`]] current active">[[+menutitle]]</span>[[+wrapper]]</li>`

  &hereClass=`current`
  &parentClass=`[[+level:gt=`1`:then=`opener2`:else=`opener`]]`
]]

Any help is highly appreciated! :slight_smile:

1 Like

Looks like you’re trying to use Modx output filters to do javascripts job. You may be better just layering the menu on top of each other using CSS and JS, rather than trying to assign a class based on it’s level within the PDO Menu call. Also, you’ll need to call pdoMenu Uncached if you want something like this to work, otherwise MODX will just return a cached version of the menu. ( [[!pdoMenu]] ) calls it uncached.

Have you got a screen shot or a link to a video to demonstrate what you’re trying to accomplish?

Thank you for helping @inside-creative!

I want to create a 2-level dropdown navigation and as you can see everything works when I click on Team 1, the nav tree stays expanded and active classes (red color) are applied correctly. When I click on Team 2 though, the second level closes. (Note that the Team Sites are Weblinks to one of its child resources)

menu

I have to admit, I was a bit lazy on the script side. I’m using a template which came with a 1-level dropdown script and I just cheated that, to work on the second dropown level as well by simply adding another Opener:

Script
var $menu = $('#menu'),
	$menu_openers = $menu.children('ul').find('.opener'),
	$menu_openers2 = $menu.children('ul').find('.opener2');

// Openers
	$menu_openers.each(function() {
		var $this = $(this);

		$this.on('click', function(event) {
			event.preventDefault();

			$menu_openers.not($this).removeClass('active');
			$this.toggleClass('active');

			$window.triggerHandler('resize.sidebar-lock');
		});

	});

// Openers 2
	$menu_openers2.each(function() {
		var $this = $(this);

		$this.on('click', function(event) {
			event.preventDefault();

			$menu_openers2.not($this).removeClass('active');
			$this.toggleClass('active');

			$window.triggerHandler('resize.sidebar-lock');
		});

	});

I don’t think that the script is the problem (might be though), but a wrong pdoMenu template which doesn’t assign the correct classes to the active entry. Like mentioned in my first post, I thought it to be right because it works on the first child (Team 1) but somehow not on the others.

If I call pdoMenu uncached, the Sub-Category will not even expand but close the parent Category.

I’m going the guess the problem is there. The level placeholder is not available in the outer part that calls the snippet. Maybe the simplest is to simply use opener as the parentClass and adjust the script? It doesn’t look like the behavior between opener and opener2 is different, altho the removeClass bit might need to be adjusted to not remove the class from the clicked parent levels.

1 Like

That’s good pointing out, I wasn’t aware of that. Looks like I’ll have to get into the script then. Not my strongest side, but will have to figure it out, I guess :wink:

So I fixed my Script to apply only opener to all parents which works fine, but it hasn’t solved my issue. Tracking this down further, I still think the problem is pdoMenu here. Take a look at this screenshot:

pdoMenu

I have selected Team 2 from the menu (see GIF above for reference).
To better visualize where each pdoMenu template is going, I have given them their respective ID. Now we can see that the first parent span actually doesn’t get the needed tplParentRowActive class (like the previous span above this parent!) but only the tplParentRow. Again: if I select Team 1, also the span directly above will become a `tplParentRowActive" element.

I thought, I might be getting things mixed up by using the tplParentRowHere and the tplParentRowActive, but the ...Here template won’t even show up at all. What am I missing?

updated pdoMenu call
[[pdoMenu?          // results don't change if called uncached...
    &parents=`0`
    &level=`3`
    &tpl=`@INLINE <li><a href="[[+link]]" [[+attributes]]>[[+menutitle]]</a>[[+wrapper]]</li>`
    &tplHere=`@INLINE <li><a href="[[+link]]" [[+classes]] [[+attributes]]>[[+menutitle]]</a>[[+wrapper]]</li>`
    &tplParentRow=`@INLINE <li><span id="tplParentRow" [[+classes]]>[[+menutitle]]</span>[[+wrapper]]</li>`
    &tplParentRowHere=`@INLINE <li><span id="tplParentRowHere" [[+classes]]>[[+menutitle]]</span>[[+wrapper]]</li>`
    &tplParentRowActive=`@INLINE <li><span id="tplParentRowActive" [[+classes]]>[[+menutitle]]</span>[[+wrapper]]</li>`
    &hereClass=`active`
    &parentClass=`opener`
]]
updated JS
var $menu = $('#menu'),
$menu_openers = $menu.children('ul').find('.opener');

$menu_openers.each(function() {
	var $this = $(this);					

	$this.on('click', function(event) {
		event.preventDefault();

		$menu_openers.filter('.active').find('+ ul').each(function(i, el) {
			var $el = $(el)

			if (!$el.has($this).length && !$el.is($this.find('+ ul'))) {
				$el.parent().find('.opener').removeClass('active')
			}
		})
		
		$this.toggleClass('active');
		$window.triggerHandler('resize.sidebar-lock');
	});
});

I would suggest to start without any dropdowns and without javascript

1 Like

So after the suggestion of @bruno17, I startet basically from scratch and rebuilt the whole menu. Turns out the issue was, that all Category and Sub-Category entries were weblinks! (Probably should have stated that more clearly to you all.) So therefore adding

&useWeblinkUrl=`0`     // Default is 1

was all I needed to get that thing finally working. Thank you all for your help! :slight_smile:

P. S. I really don’t like claiming my own post as a solution, but I guess in this case it’s the most useful for anyone else with the same issue…

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.