How to add custom plugin as menu item in customer my account navigation

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.
5 years ago
Hello all,

I am looking to add a new menu item for my plugin to the customers My Account menu, similarly to the request posted here:  https://www.nopcommerce.com/boards/t/45694/adding-menu-items-to-customer-navigation.aspx

I've tried to follow along with the suggestion and tutorial as shown in L.K.'s response, but it looks as though those predate the move over to .Net Core. I am just curious if this is still the proper approach for the most recent version of nopCommerce? If so, does anyone know of any helpful guides that may assist me with achieving this?

Thanks!
5 years ago
It works the same way except that now you'll move everything to Component instead of your controller. You'll need to create a Widget plugin.

You should see the Google Analytics plugin to get an idea of how to do that.

Hope that helps.
Regards,
Anshul
5 years ago
Thanks Anshul, I will start with this.
4 years ago
Hello dear nopCommerce Community!

I have been struggling with the documentation of nopCommerce and all the suggestions in tutorials and forum threads I could find on the internet but I just can't make a sense in how to do what I want to achieve.

This thread title precisely describes my intent. I need an extra navigation item in the customer profile page that displays some data that is related to a plugin I develop.


RoastedBytes wrote:
It works the same way except that now you'll move everything to Component instead of your controller. You'll need to create a Widget plugin.

You should see the Google Analytics plugin to get an idea of how to do that.

Hope that helps.
Regards,
Anshul

Can you please help me with a good reference link with an example or a little more detailed instructions on how to do that?

I am using version 4.20.

Any help would be highly appreciated!
Thank you in advance,

Rom
4 years ago
Update: After quite some tiresome research I managed to extend the user profile navigation items by overriding the registered ICustomerModelFactory.


    public class DependencyRegistrar : IDependencyRegistrar
    {
        public virtual void Register(ContainerBuilder builder, ITypeFinder typeFinder, NopConfig config)
        {
            builder.RegisterType<ExtendedCustomerModelFactory>()
                .As<ICustomerModelFactory>()
                .WithParameter(ResolvedParameter.ForNamed<ICacheManager>("nop_cache_static"))
                .InstancePerLifetimeScope();
        }

        public int Order => 4;
    }


The overridden class:

    public partial class ExtendedCustomerModelFactory : CustomerModelFactory
    {
        private readonly ILocalizationService _localizationService;

        // at this point I redacted the ctor and its thousand arguments to not clutter the code snippet

        public override CustomerNavigationModel PrepareCustomerNavigationModel(int selectedTabId = 0)
        {
            var model = base.PrepareCustomerNavigationModel(selectedTabId);
            var navItems = model.CustomerNavigationItems;

            navItems.Insert(
                navItems.IndexOf(navItems.SingleOrDefault(n => n.Tab == CustomerNavigationEnum.Orders)),
                new CustomerNavigationItemModel
                {
                    RouteName = "LicenseOverview",
                    Title = _localizationService
                        .GetLocaleStringResourceByName("Nop.Plugin.Misc.MyPlugin.Title")
                        ?.ResourceValue,
                    Tab = (CustomerNavigationEnum)ExtendedCustomerNavigationEnum.LicenseOverview,
                    ItemClass = "license-overview"
                });

            return model;
        }

        public enum ExtendedCustomerNavigationEnum
        {
            // must not conflict with possible values of CustomerNavigationEnum
            LicenseOverview = 200
        }
    }


I have seen many people looking for a solution for this, so hopefully this helps someone else out there.

So now I have to figure out how to hook this up with a route and a view displaying my custom plugin data.
4 years ago
Thanks for that I just adjusted my routine to call the base and add the extra item the same as you have done

To call it the way I did it was to add a custom version of \Presentation\Nop.Web\Views\Shared\Components\CustomerNavigation\Default.cshtml in my plugin structure
@model Nop.Web.Models.Customer.CustomerNavigationModel
@using Nop.Web.Framework.Infrastructure

<div class="block block-account-navigation">
    <div class="title">
        <strong>@T("Account.Navigation")</strong>
    </div>
    <div class="listbox">
        <ul class="list">
            @await Component.InvokeAsync("Widget", new { widgetZone = PublicWidgetZones.AccountNavigationBefore })
            @foreach (var item in Model.CustomerNavigationItems)
            {
                <li class="@item.ItemClass">
                    <a href="@Url.RouteUrl(item.RouteName)" class="@(Model.SelectedTab == item.Tab ? "active" : "inactive")">@(item.Title)</a>
                </li>
            }
            @await Component.InvokeAsync("Widget", new { widgetZone = PublicWidgetZones.AccountNavigationAfter })
        </ul>
    </div>
</div>

Then in my CustomViewEngine added
                            else if (context.ViewName == "Components/CustomerNavigation/Default")
                            {
                                viewLocations = new[] {
                                        $"~/Plugins/Group.Name/Views/Shared/Components/CustomCustomerNavigation/Default.cshtml"
                                        }
                               .Concat(viewLocations);

And added a routine in Components
using Microsoft.AspNetCore.Mvc;
using Nop.Plugin.Group.Name.Factories;
using Nop.Web.Framework.Components;

namespace Nop.Plugin.Group.Name.Components
{
    public class CustomCustomerNavigationViewComponent : NopViewComponent
    {
        private readonly ICustomCustomerModelFactory _customCustomerModelFactory;

        public CustomCustomerNavigationViewComponent(ICustomCustomerModelFactory customCustomerModelFactory)
        {
            _customCustomerModelFactory = customCustomerModelFactory;
        }

        public IViewComponentResult Invoke(int selectedTabId = 0)
        {
            var model = _customCustomerModelFactory.PrepareCustomerNavigationModel(selectedTabId);
            return View(model);
        }
    }
}
4 years ago
So I haven't quite yet figured out how to get a plugin View working inside the customer profile. I've registered a route with a method from my plugin Controller, which works so far, but then I get the ASP error that the View I try to return was not found. The path that should point to my plug-in View is exactly like in the other pre-installed plugins (using the full path with a ~ at the start), but somehow their Views' path gets resolved and mine does not. I quadruple checked the path, file extension and whatnot. Could this possibly have something to do with how the customer profile view itself is assembled?
4 years ago
I did not use the override or add anything to DependencyRegistrar as this is a component
In addition to my code above I added this to my plugin RouteProvider          
routeBuilder.MapRoute("Nop.Plugin.Group.CustomerCalender", "Plugins/Name/CustomerCalendar",
                        new { controller = "CustomCustomer", action = "CustomerCalendar" });
4 years ago
Yidna wrote:
I did not use the override or add anything to DependencyRegistrar as this is a component
In addition to my code above I added this to my plugin RouteProvider          
routeBuilder.MapRoute("Nop.Plugin.Group.CustomerCalender", "Plugins/Name/CustomerCalendar",
                        new { controller = "CustomCustomer", action = "CustomerCalendar" });


Thank you. Can you provide an example on how the controller action and the view have to look like and where they need to be placed?
4 years ago
Nevermind, the solution one can find in tutorials is just fine. I just forgot to tag my template to copy when building the project...

Thanks again for the tips :)
This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.