Advanced Category Navigation

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.
9 years ago
ngtrian wrote:
Hi!
Can you make from subcategory 3,4... only show when current subcategory opening, like in default category.
Thank!

Computers (heading)
      Desktops
            All in one (subcategory 3- only show when opening)
            PC
      Notebooks
      Accessories
      Software & Games
Electronics (heading)
      Camera, photo
      Cell phones


Here you are :).
I had code refactoring for it, please have a check (replace entire "_SeparatedCategoryNavigation.cshtml" file)

@using Nop.Core.Domain.Catalog
@using Nop.Core.Infrastructure
@using Nop.Services.Catalog
@{
    //current category ID
    var currentCategoryId = 0;
    if (Url.RequestContext.RouteData.Values["controller"].ToString().Equals("catalog", StringComparison.InvariantCultureIgnoreCase) &&
        Url.RequestContext.RouteData.Values["action"].ToString().Equals("category", StringComparison.InvariantCultureIgnoreCase))
    {
        currentCategoryId = Convert.ToInt32(Url.RequestContext.RouteData.Values["categoryId"].ToString());
    }

    var allCategories = EngineContext.Current.Resolve<ICategoryService>().GetAllCategories();
    var allLevel1Categories = allCategories.Where(i => i.ParentCategoryId == 0);
}
@functions
{
    public bool ContainsSelectedCategory(int selectedCategoryId, int ancestorCategoryId, IEnumerable<Category> allCategories)
    {
        var selectedCategory = allCategories.FirstOrDefault(i => i.Id == selectedCategoryId);
        if (selectedCategory == null)
        {
            return false;
        }

        if (selectedCategory.ParentCategoryId == ancestorCategoryId)
        {
            return true;
        }

        return ContainsSelectedCategory(selectedCategory.ParentCategoryId, ancestorCategoryId, allCategories);
    }
}
@helper RenderCategoryList(int selectedCategoryId, int parentCategoryId, bool generateSubCategories, IEnumerable<Category> allCategories)
{
    var subCategories = EngineContext.Current.Resolve<ICategoryService>().GetAllCategoriesByParentCategoryId(parentCategoryId);
    if (!subCategories.Any() || !(generateSubCategories || ContainsSelectedCategory(selectedCategoryId, parentCategoryId, allCategories)))
    {
        return;
    }

    <ul class="list">
        @RenderCategoryLine(selectedCategoryId, subCategories, allCategories)
    </ul>
}
@helper RenderCategoryLine(int selectedCategoryId, IEnumerable<Category> categories, IEnumerable<Category> allCategories)
{
    var isSelected = false;
    foreach (var category in categories)
    {
        isSelected = category.Id == selectedCategoryId;
        <li class="@(isSelected ? "active" : "inactive")">
            @RenderCategoryLink(category)
            @RenderCategoryList(selectedCategoryId, category.Id, isSelected, allCategories)
        </li>
    }
}
@helper RenderCategoryLink(Category category)
{
    <a href="@Url.RouteUrl("Category", new { SeName = category.ToModel().SeName })">@category.Name</a>
}
@if (allLevel1Categories.Any())
{
    foreach (var category in allLevel1Categories)
    {
        <div class="block block-category-navigation">
            <div class="title">
                @RenderCategoryLink(category)
            </div>
            <div class="listbox">
                @RenderCategoryList(currentCategoryId, category.Id, true, allCategories)
            </div>
        </div>
    }
}

Hope this help :)
9 years ago
Thank to ima9ines
Good look to you!
9 years ago
I create a file _SeparatedCategoryNavigationCurrent.cshtml in _ColumnsTwo view that only show block isSelected

How to using if  isSelected = category.Id == selectedCategoryId;
9 years ago
ngtrian wrote:
I create a file _SeparatedCategoryNavigationCurrent.cshtml in _ColumnsTwo view that only show block isSelected

How to using if  isSelected = category.Id == selectedCategoryId;


Don't really got your point :)

Please make more clearly about "How to using if  isSelected = category.Id == selectedCategoryId;".

Thanks
9 years ago
ngtrian wrote:
I create a file _SeparatedCategoryNavigationCurrent.cshtml in _ColumnsTwo view that only show block isSelected

How to using if  isSelected = category.Id == selectedCategoryId;


Hi,

The AIO solution here for you :), with following features:
- With 3 columns layout (ex.: homepage), show entire category hierarchical structure separately by top category level.
- With 2 columns layout (ex.: a category details page), show only active category hierarchical.

Steps to do it:

Step 1:

- Modify code in the "Themes/DefaultClean/Views/Shared/_ColumnsTwo.cshtml" file

  BEFORE

@Html.Action("CategoryNavigation", "Catalog", new { currentCategoryId = currentCategoryId, currentProductId = currentProductId })
        @Html.Partial("_SeparatedCategoryNavigation")
        @Html.Widget("left_side_column_after_category_navigation")

  AFTER

@Html.Action("CategoryNavigation", "Catalog", new { currentCategoryId = currentCategoryId, currentProductId = currentProductId })
        @Html.Partial("_SeparatedCategoryNavigation", /*Show active hierarchical only*/true)
        @Html.Widget("left_side_column_after_category_navigation")

- Modify code in the "Themes/DefaultClean/Views/Shared/_ColumnsThree.cshtml" file

  BEFORE

@Html.Action("CategoryNavigation", "Catalog", new { currentCategoryId = currentCategoryId, currentProductId = currentProductId })
        @Html.Partial("_SeparatedCategoryNavigation")
        @Html.Widget("left_side_column_after_category_navigation")

  AFTER

@Html.Action("CategoryNavigation", "Catalog", new { currentCategoryId = currentCategoryId, currentProductId = currentProductId })
        @Html.Partial("_SeparatedCategoryNavigation", /*Show active hierarchical only*/false)
        @Html.Widget("left_side_column_after_category_navigation")


Step 2:

- Replace entire "Themes/DefaultClean/Views/Shared/_SeparatedCategoryNavigation.cshtml" code, with the new code

@using Nop.Core.Domain.Catalog
@using Nop.Core.Infrastructure
@using Nop.Services.Catalog
@model bool
@{
    //current category ID
    var currentCategoryId = 0;
    if (Url.RequestContext.RouteData.Values["controller"].ToString().Equals("catalog", StringComparison.InvariantCultureIgnoreCase) &&
        Url.RequestContext.RouteData.Values["action"].ToString().Equals("category", StringComparison.InvariantCultureIgnoreCase))
    {
        currentCategoryId = Convert.ToInt32(Url.RequestContext.RouteData.Values["categoryId"].ToString());
    }

    var allCategories = EngineContext.Current.Resolve<ICategoryService>().GetAllCategories();
    var allLevel1Categories = allCategories.Where(i => i.ParentCategoryId == 0);

    var onlyShowActiveHierarchy = Model;
}
@functions
{
    public bool ContainsSelectedCategory(int selectedCategoryId, int ancestorCategoryId, IEnumerable<Category> allCategories)
    {
        if (selectedCategoryId == ancestorCategoryId)
        {
            return true;
        }

        var selectedCategory = allCategories.FirstOrDefault(i => i.Id == selectedCategoryId);
        if (selectedCategory == null)
        {
            return false;
        }

        if (selectedCategory.ParentCategoryId == ancestorCategoryId)
        {
            return true;
        }

        return ContainsSelectedCategory(selectedCategory.ParentCategoryId, ancestorCategoryId, allCategories);
    }
}
@helper RenderCategoryList(int selectedCategoryId, int parentCategoryId, bool generateSubCategories, IEnumerable<Category> allCategories)
{
    var subCategories = EngineContext.Current.Resolve<ICategoryService>().GetAllCategoriesByParentCategoryId(parentCategoryId);
    if (!subCategories.Any() || !(generateSubCategories || ContainsSelectedCategory(selectedCategoryId, parentCategoryId, allCategories)))
    {
        return;
    }

    <ul class="list">
        @RenderCategoryLine(selectedCategoryId, subCategories, allCategories)
    </ul>
}
@helper RenderCategoryLine(int selectedCategoryId, IEnumerable<Category> categories, IEnumerable<Category> allCategories)
{
    var isSelected = false;
    foreach (var category in categories)
    {
        isSelected = category.Id == selectedCategoryId;
        <li class="@(isSelected ? "active" : "inactive")">
            @RenderCategoryLink(category)
            @RenderCategoryList(selectedCategoryId, category.Id, isSelected, allCategories)
        </li>
    }
}
@helper RenderCategoryLink(Category category)
{
    <a href="@Url.RouteUrl("Category", new { SeName = category.ToModel().SeName })">@category.Name</a>
}
@if (allLevel1Categories.Any())
{
    foreach (var category in allLevel1Categories)
    {
        if (onlyShowActiveHierarchy && !ContainsSelectedCategory(currentCategoryId, category.Id, allCategories))
        {
            continue;
        }

        <div class="block block-category-navigation">
            <div class="title">
                @RenderCategoryLink(category)
            </div>
            <div class="listbox">
                @RenderCategoryList(currentCategoryId, category.Id, true, allCategories)
            </div>
        </div>
    }
}

Hope this help :)
9 years ago
Awesome
Thank you so much!
9 years ago
UPDATED (show separated category navigation in a product details page)

@using Nop.Core.Domain.Catalog
@using Nop.Core.Infrastructure
@using Nop.Services.Catalog
@model bool
@{
    var categoryService = EngineContext.Current.Resolve<ICategoryService>();
    var allCategories = categoryService.GetAllCategories();
    var allLevel1Categories = allCategories.Where(i => i.ParentCategoryId == 0);

    var onlyShowActiveHierarchy = Model;
    
    //current category ID
    var currentCategoryId = 0;
    if (Url.RequestContext.RouteData.Values["controller"].ToString().Equals("catalog", StringComparison.InvariantCultureIgnoreCase) &&
        Url.RequestContext.RouteData.Values["action"].ToString().Equals("category", StringComparison.InvariantCultureIgnoreCase))
    {
        currentCategoryId = Convert.ToInt32(Url.RequestContext.RouteData.Values["categoryId"].ToString());
    }

    //current product ID
    var currentProductId = 0;
    if (Url.RequestContext.RouteData.Values["controller"].ToString().Equals("product", StringComparison.InvariantCultureIgnoreCase) &&
        Url.RequestContext.RouteData.Values["action"].ToString().Equals("productdetails", StringComparison.InvariantCultureIgnoreCase))
    {
        currentProductId = Convert.ToInt32(Url.RequestContext.RouteData.Values["productId"].ToString());
    }

    if (currentProductId > 0)
    {
        var productCategories = categoryService.GetProductCategoriesByProductId(currentProductId);
        if (productCategories.Any())
        {
            currentCategoryId = productCategories[0].CategoryId;
        }
    }
}
@functions
{
    public bool ContainsSelectedCategory(int selectedCategoryId, int ancestorCategoryId, IEnumerable<Category> allCategories)
    {
        if (selectedCategoryId == ancestorCategoryId)
        {
            return true;
        }

        var selectedCategory = allCategories.FirstOrDefault(i => i.Id == selectedCategoryId);
        if (selectedCategory == null)
        {
            return false;
        }

        if (selectedCategory.ParentCategoryId == ancestorCategoryId)
        {
            return true;
        }

        return ContainsSelectedCategory(selectedCategory.ParentCategoryId, ancestorCategoryId, allCategories);
    }
}
@helper RenderCategoryList(int selectedCategoryId, int parentCategoryId, bool generateSubCategories, IEnumerable<Category> allCategories)
{
    var subCategories = EngineContext.Current.Resolve<ICategoryService>().GetAllCategoriesByParentCategoryId(parentCategoryId);
    if (!subCategories.Any() || !(generateSubCategories || ContainsSelectedCategory(selectedCategoryId, parentCategoryId, allCategories)))
    {
        return;
    }

    <ul class="list">
        @RenderCategoryLine(selectedCategoryId, subCategories, allCategories)
    </ul>
}
@helper RenderCategoryLine(int selectedCategoryId, IEnumerable<Category> categories, IEnumerable<Category> allCategories)
{
    var isSelected = false;
    foreach (var category in categories)
    {
        isSelected = category.Id == selectedCategoryId;
        <li class="@(isSelected ? "active" : "inactive")">
            @RenderCategoryLink(category)
            @RenderCategoryList(selectedCategoryId, category.Id, isSelected, allCategories)
        </li>
    }
}
@helper RenderCategoryLink(Category category)
{
    <a href="@Url.RouteUrl("Category", new { SeName = category.ToModel().SeName })">@category.Name</a>
}
@if (allLevel1Categories.Any())
{
    foreach (var category in allLevel1Categories)
    {
        if (onlyShowActiveHierarchy && !ContainsSelectedCategory(currentCategoryId, category.Id, allCategories))
        {
            continue;
        }

        <div class="block block-category-navigation">
            <div class="title">
                @RenderCategoryLink(category)
            </div>
            <div class="listbox">
                @RenderCategoryList(currentCategoryId, category.Id, true, allCategories)
            </div>
        </div>
    }
}
9 years ago
Thank again
Good solution Category
Hope more options category navigation in next nopCommerce
8 years ago
Hi
Category title do not translated when change language
Can you fix help me
Thanks
8 years ago
ngtrian wrote:
Hi
Category title do not translated when change language
Can you fix help me
Thanks


Hi,

Did you enter the category name for second language?
This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.