Press "Enter" to skip to content

APEX Media List Mega Menu

When I showed the Inline Popup Region to my coworker Shakeeb, he said he wanted to put a media list in it and use it as a navigation menu. And I said why not just use a menu. This was all theoretical at that point because as far as I know no one had done this before.

But the menu widget does have an option to use custom markup for the content. If you look at the APEX builder in the upper right corner there is an account menu with your user name. This is implemented with the menu widget even though it looks nothing like a normal drop down or popup menu. If you view the source of the account menu button you will see that it has the js-menuButton class and the data-menu attribute just like any menu button would. And if this is a menu button then it must open a menu.

The account menu was added in the APEX 5.0 release and at this time mega menus were all the rage. Mega menus are used for navigation like normal menus but don’t follow the same rigid layout rules. They can contain extra information, multiple columns, indented lists, icons or images, and so on. They don’t have nested popup sub menus, or checkbox or radio items. Shakeeb had a good idea of what he wanted for the account menu and created a prototype but we didn’t have any kind of region or widget that worked like a mega menu. Rather than create something new from scratch or use a 3rd party library I suggested enhancing the menu widget, that was already under development for 5.0, so that it could also meet the needs of the account menu.

Since then I don’t think the custom content/mega menu capability of the menu widget has been used for anything other than the builder account menu. I briefly mentioned this custom content in a previous blog article: “There is a custom content feature of the menu but I don’t recommend using it because it is not mature enough. It is only used for the APEX builder account menu.”. If you look at the 18.1 preview JavaScript API documentation you will find the customContent option and the rules for the markup with this note: “custom menu content is an experimental feature and may change substantially in the future.”.

So if this is not mature and experimental why am I writing about it? What has changed? Nothing has really changed. The menu widget has changed very little since 5.0 including the custom content feature. It is still experimental and may change but the passing of time can give the impression of stability. The reason I set out to show a media list as a mega menu is that Shakeeb had a compelling use case for a media list and I think that a mega menu it is a better implementation than using an inline popup region (or any popup in general). The mega menu is better because:

  • You don’t need a dynamic action to open it because it works with menu buttons.
  • It automatically opens under the menu button.
  • It is semantically more correct to use a menu for navigation. For accessibility it has all the proper menu roles.
  • Keyboard navigation is already supported.

The time is right to try out this mega menu functionality. I created a variation of the 18.1 New Region Features app from my previous blog article called the Mega Menu edition. You can download it here.

Mega Menu example

The rest of this article will explain how to do it. I did this in the 18.1 release that you can find on apex.oracle.com (currently a pre-release). This may work for APEX 5.1 as well. I didn’t try it but let me know if you get it working.

The solution is a list template that is a cross between Menu Popup and Media List. Here are the steps:

  1. Make a copy of the Universal Theme Meda List template. Call it “Mega Menu”. For the Template Identifier use <your-unique-prefix>_MEGA_MENU.
  2. In the Before Rows template add:
        <div id="#PARENT_STATIC_ID#_menu" class="a-Menu-content mega-menu" style="display:none;">
    

    before the <ul>.

  3. Add class a-Menu-label to the anchor element in the List Template Current and List Template Noncurrent templates. The result should look like this:
        <a href="#LINK#" class="t-MediaList-itemWrap a-Menu-label #A05#" #A03#>
    
  4. Add </div> after the </ul> in the after rows template. That is the last of the markup changes. As you can see they are very minimal. Just adding a wrapping div to indicate the menu content and adding a class to indicate the menu item label.
  5. Add the following JavaScript code to the Execute When Page Loads attribute:
        var e = apex.jQuery("##PARENT_STATIC_ID#_menu", apex.gPageContext$);
        e.menu({ customContent: true });
    

    This is a simplified version of the code in the Menu Popup template.

  6. Now the biggest change is some CSS. Add the following to the Cascading Style Sheet: Inline attribute:
    .a-Menu-content.mega-menu {
        width: 70%;
        padding: 0;
    }
    .a-Menu-content.mega-menu .a-Menu-label,
    .a-Menu-content.mega-menu .a-Menu-item {
        display: inherit;
    }
    .a-Menu-content.mega-menu .is-active .t-MediaList-title {
        font-weight: bold;
    }
    .a-Menu-content.mega-menu .t-MediaList-desc {
        white-space: normal;
    }
    .a-Menu-content.mega-menu .a-Menu-item {
        transition: none;
    }
    .a-Menu-content.mega-menu .is-focused .t-MediaList-desc {
        color: #FFF;
    }
    .a-Menu-content.mega-menu .is-focused .t-MediaList-icon {
        background: rgba(255,255,255,.5);
        color: #0572CE !important;
    }
    

    These rules are needed to give the container a width, because the mega menu assumes it is in a container with some reasonable width, and resolve some conflicts between menu and media list rules. Shakeeb gave me a few styles to apply to make it look better when a menu item is focused.

This new Mega Menu list template can be used just like you would use the Menu Popup template. I previously described how to make a Simple Popup Menu using the Menu Popup list template and how to open it with a menu button.

A nice thing about this Mega Menu is that it has all the nice behaviors of the APEX menu widget and the pleasing style and responsive behaviors of the Universal Theme media list. As you can see it allows you to give a specific style to the active page (in this case bold) which is something you can’t do with a normal popup menu. Here is the same menu on a smaller screen showing the responsive behavior. You can play around with the Mega Menu template options to control the number of columns and more.

Responsive Mega Menu

It should be clear from this example that all kinds of mega menus could be created using this same list template technique or from a PL/SQL region, report region, or a custom region plug-in. It could be done for other themes as well. All it takes is some HTML and CSS skills.

The toughest part of getting this to work for me was figuring out the little CSS tweaks. Other than that it went very smoothly. There were two small issues specific to the New Region Features app and the way it handles the next and previous navigation buttons. I described how the next and previous buttons find the page by looking at the hrefs in the menu items array in my last blog article. One difference is that the hrefs in the custom menu are full URLs so I had to strip off the URL before the parameters. The bigger issue is that the menu widget doesn’t initialize the items array from the markup until the first time it is opened. This should not normally be a problem unless you are doing some extra menu customization. Even then you may be able to use the beforeopen event. In this case I open the menu off screen and closed it when the page loads. Check out these changes and the mega menu in this updated Mega Menu edition of the New Region Features app. Remember to install the Sample Interactive Grids and Sample Charts apps first.

If you create your own mega menu share a picture.

One Comment

  1. Heifi
    Heifi Tuesday, May 8, 2018

    Hi,

    Nice feauture, works well in 5.1. as well.

    I tried to put a classic report into a mega menu which works as well.

    Next step I tried to have a report with a popup menu on each row to show a mega-menu ==> works as well.

    Next step, show a classic report on each row showing detail data for the selected row ==> Problem, the mega-menu classic report does not update even though the filter value properly changes in session state, but apex.trigger does not seem to affect the report at all.

    Any idea why?

    Thanks

Comments are closed.