Reputation: 69
The site consists of 2 menus:
Secondary menu description: When selecting for example "company" from the main menu, the main menu shows a secondary level with company 1, company 2 and so on.
Main Menu:
When selecting Company 1 or Company 2 the secondary menu appears.
Secondary menu (this menu does not have levels into it, just items belonging to this company):
Question:
When selecting for example Company 1 the contact session will be that of Company 1. When selecting company 2 the contact menu option of the secondary menu will be that of company 2.
How exactly can I make this into Orchard? Currently I have 2 navigation, 1 menu widget for the main menu and 1 menu widget for the secondary menu.
When selecting one of the companies on the main menu my secondary menu appears (this menu is added to a layer with a url rule below). The level of this navigation is set to 1. Url rule:
~/Company/*
But how exactly will the items on the secondary menu redirect to other content items depending on what company I have selected in the main menu?
Thanks.
Upvotes: 0
Views: 400
Reputation: 2164
This is a really good post on how to dynamically inject navigation items into your menu: http://www.davidhayden.me/blog/dynamically-injecting-menu-items-in-orchard-cms
Also, if you are on Orchard 1.6 I would apply this fix so that the items show when you are logged out (there is a permission issue if you don't update the Reduce method in the NavigationManager.cs class: https://orchard.codeplex.com/workitem/19318#CommentContainer1
EDIT:
using System.Collections.Generic;
using System.Linq;
using Orchard.ContentManagement;
using Orchard.Localization;
using Orchard.Projections.Models;
using Orchard.Projections.Services;
using Orchard.UI.Navigation;
namespace Orchard.Projections.Navigation {
/// <summary>
/// Dynamically injects query results as menu items on NavigationQueryMenuItem elements
/// </summary>
public class NavigationQueryProvider : INavigationFilter {
private readonly IContentManager _contentManager;
public NavigationQueryProvider(IContentManager contentManager) {
_contentManager = contentManager;
}
public IEnumerable<MenuItem> Filter(IEnumerable<MenuItem> items) {
foreach (var item in items) {
if (item.Content != null && item.Content.ContentItem.ContentType == "CompanyMenuItem") {
var containedItems = GetContainedItems(item.Id).Select(record => new MenuItem{
//fill all properties
};
var menuPosition = item.Position;
int index = 0;
foreach (var contentItem in contentItems) {
if (contentItem != null) {
var part = contentItem;
var menuText = _contentManager.GetItemMetadata(part).DisplayText;
var routes = _contentManager.GetItemMetadata(part).DisplayRouteValues;
var inserted = new MenuItem {
Text = new LocalizedString(menuText),
IdHint = item.IdHint,
Classes = item.Classes,
Url = item.Url,
Href = item.Href,
LinkToFirstChild = false,
RouteValues = routes,
LocalNav = item.LocalNav,
---> Items = containedItems,
Position = menuPosition + ":" + index++,
Permissions = item.Permissions,
Content = part
};
yield return inserted;
}
}
}
else {
yield return item;
}
}
}
public IEnumerable<ContentItem> GetContainedtems(int Id) {
var container = _contentManager.Query<ContainerPart>().List().SingleOrDefault(x => x.Id == Id);
IContentQuery<ContentItem> query = _contentManager
.Query(VersionOptions.Published)
.Join<CommonPartRecord>()
.Where(x => x.Container.Id == Id);
var descendingOrder = container.OrderByDirection == (int)OrderByDirection.Descending;
query = query.OrderBy(container.OrderByProperty, descendingOrder);
var contentItems = query.List();
return contentItems;
}
}
}
Note* I haven't tested this, but basically I believe the best way to do this is create a container and add all the related content items for the specific company and then query the contained items. Just add the Containable and Container parts to the Page Content Type (or whatever content type you are using).
Upvotes: 1