Ready for part 4? Yes, part 4. We continue our small walkthrough of building your own Admin Module in ContentBox 3. The last few blog posts we learned the minimum requirements for a new module, to be controlled from inside of ContentBox. Then we learned how to add a handler and a view, and how to access the module from the front end entry point, and through the ContentBox admin entrypoint. In the last blog post in this mini series, we looked at adding a Submenu for your module, to an existing top level Menu item inside of the ContentBox admin. This blog post is going to show you how to add your very own top level Menu item, give it an icon, set permissions, and then add Submenu items to access your module.

Existing code to add a submenu item

As we learned in the previous posts, we need to add code to the onLoad and onUnload functions inside your ModuleConfig.cfc file. 
To add a submenu item to an existing menu, we used the following code.

/**
* Fired when the module is registered and activated.
*/
function onLoad(){
     // Let's add ourselves to the main menu in the Modules section
     var menuService = controller.getWireBox().getInstance( "AdminMenuService@cb" );
     // Add Menu Contribution
     menuService.addSubMenu(
          topMenu=menuService.MODULES,
          name="mySecretsSubMenu",
          label="Find My Secrets",
          href="#menuService.buildModuleLink('mysecrets','home')#"
     );
}

Adding our own top level menu item

This code is a great start, we just need to insert another line between getting the MenuService, and adding the subMenu. This is where we create the topMenu Item.

// Add Menu Contribution
menuService.addTopMenu(
     name         = "MY_SECRET_MODULES_MENU",
     label        = "<i class='fa fa-user-secret'></i> My Secret Modules",
     permissions = "PAGES_EDITOR"
);
  • name - this is the programmatic reference to the top menu item. Its an internal ContentBox convention to make it capitalized with underscores. 
  • label - this is the top menu label itself. You can use Font Awesome Icons to make your menu stand out, just prepend the icon like we have here. You can use icons for the submenus as well, but space is limited, so they look better only being used at the top level menu items.
  • permissions - this is where you can set permissions to view this menu item. I have just used PAGES_EDITOR in this case, because most users could access this. We recommend that you add permissions to ContentBox, assign them to roles, and then you can restrict your menus based on who is logged in.

Note: the permissions listed here only determine whether the user logged in can see the top level menu item. If the user does not have permission to see the top level menu item, that does not stop them from accessing the module itself through the admin. I think we should cover securing Custom Modules in a future post.

Add submenu to our new top level menu

Now we have added our top menu item, we need to change the code we used to add the Submenu item. We need to update the submenu to be added to our new top level menu item "MY_SECRET_MODULES_MENU", instead of the MenuService.MODULES, just switch them out and your file onLoad() should look like this

/**
* Fired when the module is registered and activated.
*/
function onLoad(){
     // Let's add ourselves to the main menu in the Modules section
     var menuService = controller.getWireBox().getInstance( "AdminMenuService@cb" );
   
     // Add Top Menu Contribution
     menuService.addTopMenu(
          name         = "MY_SECRET_MODULES_MENU",
          label        = "<i class='fa fa-user-secret'></i> My Secret Modules",
          permissions = "PAGES_EDITOR"
     );
     // Add Sub Menu Contribution
     menuService.addSubMenu(
          topMenu="MY_SECRET_MODULES_MENU",
          name="mySecretsSubMenu",
          label="Find My Secrets",
          href="#menuService.buildModuleLink('mysecrets','home')#"
     );
}

Removing the Submenu and TopMenu onUnload()

We need to update the removeSubMenu to reference our new top menu. We can remove MenuService.MODULES and replace it with "MY_SECRET_MODULES_MENU". After that line, we have successfully removed the Submenu item, we can remove the TopMenu iteam as well, with one line. You can see it all below.

/**
* Fired when the module is unregistered and unloaded
*/
function onUnload(){
     // Let's remove ourselves to the main menu in the Modules section
     var menuService = controller.getWireBox().getInstance( "AdminMenuService@cb" );
     // Remove Menu Contribution
     menuService.removeSubMenu(topMenu= "MY_SECRET_MODULES_MENU",name="mySecretsSubMenu" );
     menuService.removeTopMenu( topMenu= "MY_SECRET_MODULES_MENU" );
}

Note: when adding top level menu items, if not sub menus exist, the top menu will not show.
https://gist.github.com/gpickin/24df5491a332853c416a6159ef4608f0

Lets have a look?

Now when you activate, it added the Top Menu and the Sub Menu items as well. Now you can group several of your modules into a single Top level menu item.
Next blog post we'll look at adding permissions to roles, and assigning to users, to show and hide the menu items, and learn how to lock down your custom module incase the user can remember the URL to access it.