Add Remove Active Class from Navigation


(Nick Papadatos) #1

Matrix Version: 6.39.2

Hello Squiz folk

Has anyone ever ran into this issue where for whatever reason you’re not using the standard menu design area but are using an Asset Lister or SSJS to render your global menu.

Then, how do you add remove the active class based on the current page path name and matching it to the href path name without having to use JavaScript.

I know there are many scenarios but would love to hear from anyone.

In this example we’re only showing the one level:

      let html = '';
      let nav =  %globals_asset_children_link_type_1:xxx^as_asset:asset_name,asset_url,asset_type_code^empty:[]%;

  html +=`<ul class="global-nav">`;
  
    nav.forEach((asset, index) => {
       if(asset.asset_type_code === 'page_standard'){
           html +=`
          <li class="nav-item">
               <a class="nav-link <add/remove active class>" href="${asset.asset_url}">
                  ${asset.asset_name}
               </a>
           </li>`;
       }
    });
    html +=`</ul>`;  
    print(html);

(Harinder Singh) #2

Asset Listing
%asset_url^eq:{frontend_asset_url}:active:inactive%

JavaScript Solution

let html = '';
let nav = %globals_asset_children_link_type_1:xxx^as_asset:asset_name,asset_url,asset_type_code^empty:[]%;
let frontendUrl = %globals_asset_url%;

html += `<ul class="global-nav">`;

nav.forEach((asset, index) => {
    let activeClass = asset.asset_url === frontendUrl ? ' active' : '';

    // Ensure compatibility with various HTML frameworks:
    html += `
        <li class="nav-item">
            <a class="nav-link ${activeClass}" href="${asset.asset_url}">
                ${asset.asset_name}
            </a>
        </li>
    `;
});

html += `</ul>`;
print(html);

(Nick Papadatos) #3

Thanks Harinder, I’m always on the lookout for your posts/solutions :slight_smile:
I’ll give your solution a go…

I ended up with the following before I read your reply:

        let html = '';
        let nav = %globals_asset_children_link_type_1:xxx^as_asset:asset_name,asset_assetid,asset_url,asset_type_code^empty:[]%;
        let assetLineage = '%frontend_asset_linking_lineage%';
    
      html +=`<ul class="global-nav">`;
      
        nav.forEach((asset, index) => {
        
               let active = assetLineage.includes(asset["asset_assetid"]);   
               html +=`
               <li class="nav-item">
                 <a class="nav-link${active ? ' active' : ''}" href="${asset.asset_url}">
                       ${asset.asset_name}
                 </a>
               </li>
             `;
        });
        html +=`</ul>`; 
        
        print(html);

(Harinder Singh) #4

Thanks, Nick! :blush: I hope it works for you. I’m glad we’re all supporting each other here.


(Nick Papadatos) #5

Just for anyone looking at this you need to include quotes:
let frontendUrl = "%globals_asset_url%";


(Iain Simmons) #6

If your Matrix instance has the ability to use ESI includes, this is an alternative method that is potentially more cache-friendly:
https://docs.squiz.net/matrix/version/latest/tutorials/designs-and-templates/create-an-esi-based-main-menu.html