Forum

Thread tagged as: Discussion

Conditionally accessing attributes for advanced navigation class output

What I ultimately want to do is to apply a class to every navigation <li> element that is the parent of a subordinate navigation level, and also to give each of those <li> elements a unique HTML 'id' attribute. I need this for my JavaScript sub-menu swapping feature to work.

I've been reading up on page attributes and tried creating a new page attribute, and then to use Perch conditionals in my navigation template, but I couldn't seem to get any results that even were unambiguously affected by selecting this new attribute template:

<perch:template path="pages/attributes/seo.html" />
<perch:pages id="subnavParent" urlify="true" />

I gave up on that and tried using variables passed to the header template (which in turn calls the navigation function). I made a separate version of the template to include the class for a sub-nav parent <li>, and I tried applying that template only for navigation items whose corresponding PHP page explicitly sets the layout variable "navparent":

specificpage.php

  <?php
    perch_layout('global.header',array(
      'navparent' => true,
    ));
  ?>

global.header.php

<?php
        if (perch_layout_has('navparent')) {
          perch_pages_navigation(array(
            'navgroup' => 'main-navigation-left',
            'template' => 'main-nav_subnav-parent.html',
            'from-path' => '/',
            'levels' => 1,
            'flat' => true,
          ));
        }
        else {
          perch_pages_navigation(array(
            'navgroup' => 'main-navigation-left',
            'template' => 'main-nav.html',
            'from-path' => '/',
            'levels' => 1,
            'flat' => true,
          ));
        }
      ?>

main-nav.html

<perch:before><nav id="nav-left" class="mq-hide">
  <ul class="component-navlist"></perch:before>
    <li<perch:if exists="current_page"> class="nav-active"</perch:if>><a href="<perch:pages id="pagePath" />"><perch:pages id="pageNavText" /></a></li>
  <perch:after></ul>
</nav></perch:after>

main-nav_subnav-parent.html

<perch:before><nav id="nav-left" class="mq-hide">
  <ul class="component-navlist"></perch:before>
    <li<perch:if exists="current_page"> class="nav-active subnav-parent"</perch:if><perch:else> class="subnav-parent"</perch:else><a href="<perch:pages id="pagePath" />"><perch:pages id="pageNavText" /></a></li>
  <perch:after></ul>
</nav></perch:after>

This doesn't address adding the "id" attribute for those <li> elements, but one problem at a time.

It doesn't work, though. My CSS shows a little caret character after <li> elements that have the class "subnav-parent," but now when viewing a page that has a sub-nav, all the navigation items are careted, while none of them are careted when viewing a page that doesn't have a sub-nav.

I need some way to pass variables with navigation items -- some variable or object representing each output navigation item -- or something. It seems like everything is page-based.

Paul Lee

Paul Lee 0 points

  • 5 years ago
Drew McLellan

Drew McLellan 2638 points
Perch Support

To find those that have children, use

<perch:if exists="subitems">
    subnav-parent
</perch:if>

For the ID, you should be able to use something like

id="page<perch:pages id="pageID" />"

Drew McLellan said:

To find those that have children, use

Hmm... I guess "subitems" is only true if sub pages are actually output in the same navigation object using the same perch_pages_navigation() call?

I have sub pages that show up as such in the dashboard, but I'm only outputting the first level of navigation. I'd like the corresponding navigation elements to get the class even though their child pages aren't being output in the same place.

For the ID, you should be able to use something like

That works as expected. I used an attribute template to provide the substrings used in navigation items' ID attributes, which is then set in the dashboard:

<perch:template path="pages/attributes/seo.html" />
<perch:pages id="pageNavType" label="Select the navigation category that this page will be grouped with, either as part of the primary navigation menu or as part of a sub-navigation group" type="select" options="about,restaurant,rooms,events,contact" divider-before="Navigation Type" />

For each page, I choose this template in the Page Options, and I select one of my ID options I specified in the <perch:pages> tag.

The navigation template uses this to output an ID attribute:

id="nav-<perch:pages id="pageNavType" />"

Happily, the ID attributes are even set for the navigation items that don't go to the current page.

Thanks for the help!

I should be able to work with this, so I'll mark it as the solution. But I wish I could set a class for navigation items corresponding to pages that have sub-pages even if the navigation object technically doesn't have subitems.

Okay, this works for me:

New page attribute template that includes the one from my previous post, used only for the pages that are parents of sub navigation:

<perch:template path="pages/attributes/seo.html" />
<perch:template path="pages/attributes/navigation-type.html" />
<perch:pages id="pageSubnav" type="text" label="This is for site configuration unrelated to content, please do not change." divider-before="Class added to navigation element" />

Then, in the conditional in the navigation template:

<li class="<perch:if exists="current_page">nav-active</perch:if><perch:if exists="pageSubnav"> subnav-parent</perch:if>" id="nav-<perch:pages id="pageNavType" />">

In the dashboard on the Page Details, for each page individually, I paste in "subnav-parent" -- the name of the class attribute.

So, it's literally all good!

Note

In the attribute template that adds the ID, I had to insert suppress="true" after the divider-before, in order to prevent the string chosen from the options from being output at the top of the page.