Easy Steps to Create Secondary Navigation from Structure Group In DXA application

Sometime user wants to create secondary navigation menu for their specific type of pages (Like Product Detail Page, Articles, etc.). I always prefer to check with user whether they are comfortable with the mechanism of Top Menu navigation then I always recommend to use the inbuilt navigation.json to generate the secondary navigation.  It’s very easy to reuse that, you just need to reconstruct the default methods.

 If you are familiar with the default DXA Navigation Provider’s methods, then you can understand the logic easily, it’s basically a combination of bread cramp and top menu. Use the logic to find the current Structure Group (Directory) from the request url and return the SitemapItem of that particular Structure Group.

 Here are the steps to generate the secondary navigation  –

On your web application

  1. Create your own NavigationProvider class and extend the DXA default NavigationProvider. 

  2. Create a method underneath that class like below -  (for full source code check this.)

    public SitemapItem GetContextSecondaryNavigationLinks(string requestUrlPath, Localization localization)
    {
    using (new Tracer(requestUrlPath, localization))
    {
    SitemapItem sitemapItem = (SitemapItem)GetNavigationModel(localization); // Start with Sitemap root Item.
    int levels = requestUrlPath.Split('/').Length;

    SitemapItem secondaryNavigationModel = new SitemapItem();

    while (levels > 1 && sitemapItem.Items != null)
    {
    sitemapItem =
    sitemapItem.Items.FirstOrDefault(
    i => requestUrlPath.StartsWith(i.Url, StringComparison.InvariantCultureIgnoreCase));
    if (sitemapItem != null)
    {
    if (sitemapItem.Type != "Page")
    {
    secondaryNavigationModel = sitemapItem;
    }
    levels--;
    }
    else
    {
    break;
    }
    }
    return secondaryNavigationModel;
    }

    }



  3. Now create your own Navigation Controller (If it is not created already)
    Overload the Navigation Action like below - (for full source code check this.)

    public class CustomNavigationsController : NavigationController
    {
    public override ActionResult Navigation(EntityModel entity, string navType, int containerSize = 0)
    {
    if (navType.Trim().ToLower() == "topmenu")
    {
    SitemapItem model = (SitemapItem)SiteConfiguration.NavigationProvider.GetNavigationModel(WebRequestContext.Localization);
    .
    .
    .
    return View(sourceModel.MvcData.ViewName, model);

    }
    else if (navType.Trim().ToLower() == "secmenu")
    {
    CustomNavigationProvider provider = new CustomNavigationProvider();
    SitemapItem model = (SitemapItem)provider.GetContextSecondaryNavigationLinks(Request.Path,WebRequestContext.Localization);

    EntityModel sourceModel = (EnrichModel(entity) as EntityModel) ?? entity;
    model.XpmMetadata = sourceModel.XpmMetadata;
    model.XpmPropertyMetadata = sourceModel.XpmPropertyMetadata;

    return View(sourceModel.MvcData.ViewName, model);
    }
    else
    {
    return base.Navigation(entity, navType, containerSize);
    }

    }
    }



    So, it will check for the NaveType value, If Navtype value is “secmenu” then it call your own Navigation provider and get the SitemapItem for current structure Group.

Note** don’t forget to Register the Custom Navigation provider under the Unity Container

On your CMs side–

  1. Create a component template for secondary navigation and mention the Route Values as navType:SecMenu. Rest of the Value will be as per your implementation. (Refer the below Image)