0

I made a PanelMenu and I tried to add an icon to the root submenu but it's not working.

<p:panelMenu>
    <p:submenu label="Üye işlemleri" icon="fa fa-user-plus">
        <p:menuitem value="Üye Kayıt" icon="fa fa-user-plus"
            action="#{redirect.toRegister()}" /> 
        <p:menuitem value="Üye Düzenle" icon="fa fa-pencil" />
    </p:submenu>
    <p:submenu label="Kullanıcı işlemleri" icon="ui-icon-extlink">
        <p:menuitem value="Anasayfa" icon="fa fa-home"
            action="#{redirect.toMainPage()}" />
        <p:menuitem value="Üye Kayıt" icon="fa fa-user-plus"
            action="#{redirect.toRegister()}" /> 
        <p:menuitem value="Üye Düzenle" icon="fa fa-pencil" />
    </p:submenu>
</p:panelMenu>

enter image description here

Do you have any idea? I also tried with ui-icon (not fontawesome). I don't want to change default submenu icon. I want to add next to default icon like on this page. You can see at the example, especially in Navigation > Link. As you can see, Link is a submenu. Does it really have to be 2 submenu inside each other for adding icon?

Edit ------

My render class get extends on "PanelMenuRenderer" and my faces-config.xml is;

<render-kit>
    <renderer>
        <component-family>org.primefaces.component</component-family>
        <renderer-type>org.primefaces.component.PanelMenuRenderer</renderer-type>
        <renderer-class>denemeExample.my</renderer-class>
    </renderer>
</render-kit>

When I try to run it I get an error .

An Error Occurred:

javax/servlet/jsp/jstl/core/Config
- Stack Trace

java.lang.NoClassDefFoundError: javax/servlet/jsp/jstl/core/Config
    at com.sun.faces.application.view.JspViewHandlingStrategy.executePageToBuildView(JspViewHandlingStrategy.java:344)
    at com.sun.faces.application.view.JspViewHandlingStrategy.buildView(JspViewHandlingStrategy.java:153)
    at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:99)
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
    at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:219)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:647)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.netbeans.modules.web.monitor.server.MonitorFilter.doFilter(MonitorFilter.java:393)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:217)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
    at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:616)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:518)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1091)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:673)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1500)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1456)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:745)

I tried to solve this adding jstl-1.2.jar and jsp-api.jar inside to WEB-INF/lib but not solved and server starts working unlogical. It doesnt work any code in xhtml like p:outputLabel or h:outputLabel. I think tomcat doesnt run. Last of all I use PrimeFaces 6.0 and jsf 2.2 . So do you have any idea what should I do ?

2 Answers2

1

Does it really have to be 2 submenu inside each other for adding icon ?

Simply yes. As stated in PrimeFaces Documentation:

First level of submenus are rendered as accordion panels and descendant submenus are rendered as tree node.

If you look at the source code, you will see that user icons in root submenus will not be taken into account in encodeRootSubmenu(). On the other hand descendant submenus user icons will be taken into account in encodeDescendantSubmenu().

One possible solution to get user icon support for root submenus in PanelMenus, is to create a custom renderer based on PanelMenuRenderer and to override encodeRootSubmenu(). Maybe this question helps you as a starting point.

Community
  • 1
  • 1
irieill
  • 1,203
  • 10
  • 32
0

This solution is maden by irieill's post. Actually its not hard what I made but each way I thought I should post it.

This is customPanelMenuRenderer (It's package is "com")

public class customPanelMenuRenderer extends BaseMenuRenderer {

@Override
protected void encodeScript(FacesContext context, AbstractMenu abstractMenu) throws IOException {
    PanelMenu menu = (PanelMenu) abstractMenu;
    String clientId = menu.getClientId(context);
    WidgetBuilder wb = getWidgetBuilder(context);
    wb.initWithDomReady("PanelMenu", menu.resolveWidgetVar(), clientId).attr("stateful", menu.isStateful());
    wb.finish();
}

@Override
protected void encodeMarkup(FacesContext context, AbstractMenu abstractMenu) throws IOException {
    ResponseWriter writer = context.getResponseWriter();
    PanelMenu menu = (PanelMenu) abstractMenu;
    String clientId = menu.getClientId(context);
    String style = menu.getStyle();
    String styleClass = menu.getStyleClass();
    styleClass = styleClass == null ? PanelMenu.CONTAINER_CLASS : PanelMenu.CONTAINER_CLASS + " " + styleClass;

    writer.startElement("div", menu);
    writer.writeAttribute("id", clientId, "id");
    writer.writeAttribute("class", styleClass, "styleClass");
    if (style != null) {
        writer.writeAttribute("style", style, "style");
    }
    writer.writeAttribute("role", "menu", null);

    if (menu.getElementsCount() > 0) {
        List<MenuElement> elements = menu.getElements();

        for (MenuElement element : elements) {
            if (element.isRendered() && element instanceof Submenu) {
                encodeRootSubmenu(context, menu, (Submenu) element);
            }
        }
    }

    writer.endElement("div");
}

protected void encodeRootSubmenu(FacesContext context, PanelMenu menu, Submenu submenu) throws IOException {
    ResponseWriter writer = context.getResponseWriter();
    String style = submenu.getStyle();
    String icon = submenu.getIcon();
    String styleClass = submenu.getStyleClass();
    styleClass = styleClass == null ? PanelMenu.PANEL_CLASS : PanelMenu.PANEL_CLASS + " " + styleClass;
    boolean expanded = submenu.isExpanded();
    String headerClass = expanded ? PanelMenu.ACTIVE_HEADER_CLASS : PanelMenu.INACTIVE_HEADER_CLASS;
    String headerIconClass = expanded ? PanelMenu.ACTIVE_TAB_HEADER_ICON_CLASS : PanelMenu.INACTIVE_TAB_HEADER_ICON_CLASS;
    System.out.println("headerIconClass = " + headerIconClass);
    System.out.println("icon = " + icon);
    boolean hasIcon = (icon != null);
    String contentClass = expanded ? PanelMenu.ACTIVE_ROOT_SUBMENU_CONTENT : PanelMenu.INACTIVE_ROOT_SUBMENU_CONTENT;

    //wrapper
    writer.startElement("div", null);
    writer.writeAttribute("class", styleClass, null);
    if (style != null) {
        writer.writeAttribute("style", style, null);
    }

    //header
    writer.startElement("h3", null);
    writer.writeAttribute("class", headerClass, null);
    writer.writeAttribute("role", "tab", null);
    writer.writeAttribute("tabindex", "0", null);

    //icon
    writer.startElement("span", null);
    writer.writeAttribute("class", headerIconClass, null);
    writer.endElement("span");

    //user icon
    if (hasIcon) {
        writer.startElement("span", null);
        writer.writeAttribute("class", "ui-icon " + icon, null);
        writer.endElement("span");
    }

    writer.startElement("a", null);
    writer.writeAttribute("href", "#", null);
    writer.writeAttribute("tabindex", "-1", null);
    writer.writeText(submenu.getLabel(), null);
    writer.endElement("a");

    writer.endElement("h3");

    //content
    writer.startElement("div", null);
    writer.writeAttribute("class", contentClass, null);
    writer.writeAttribute("role", "tabpanel", null);
    writer.writeAttribute("id", menu.getClientId(context) + "_" + submenu.getId(), null);
    writer.writeAttribute("tabindex", "0", null);

    if (submenu.getElementsCount() > 0) {
        List<MenuElement> elements = submenu.getElements();

        writer.startElement("ul", null);
        writer.writeAttribute("class", PanelMenu.LIST_CLASS, null);

        for (MenuElement element : elements) {
            if (element.isRendered()) {
                if (element instanceof MenuItem) {
                    MenuItem menuItem = (MenuItem) element;
                    String containerStyle = menuItem.getContainerStyle();
                    String containerStyleClass = menuItem.getContainerStyleClass();
                    containerStyleClass = (containerStyleClass == null) ? Menu.MENUITEM_CLASS : Menu.MENUITEM_CLASS + " " + containerStyleClass;

                    writer.startElement("li", null);
                    writer.writeAttribute("class", containerStyleClass, null);
                    if (containerStyle != null) {
                        writer.writeAttribute("style", containerStyle, null);
                    }
                    encodeMenuItem(context, menu, menuItem);
                    writer.endElement("li");
                } else if (element instanceof Submenu) {
                    encodeDescendantSubmenu(context, menu, (Submenu) element);
                }
            }
        }

        writer.endElement("ul");
    }

    writer.endElement("div");   //content

    writer.endElement("div");   //wrapper
}

protected void encodeDescendantSubmenu(FacesContext context, PanelMenu menu, Submenu submenu) throws IOException {
    ResponseWriter writer = context.getResponseWriter();
    String icon = submenu.getIcon();
    String style = submenu.getStyle();
    String styleClass = submenu.getStyleClass();
    styleClass = styleClass == null ? PanelMenu.DESCENDANT_SUBMENU_CLASS : PanelMenu.DESCENDANT_SUBMENU_CLASS + " " + styleClass;
    boolean expanded = submenu.isExpanded();
    String toggleIconClass = expanded ? PanelMenu.DESCENDANT_SUBMENU_EXPANDED_ICON_CLASS : PanelMenu.DESCENDANT_SUBMENU_COLLAPSED_ICON_CLASS;
    String listClass = expanded ? PanelMenu.DESCENDANT_SUBMENU_EXPANDED_LIST_CLASS : PanelMenu.DESCENDANT_SUBMENU_COLLAPSED_LIST_CLASS;
    boolean hasIcon = (icon != null);
    String linkClass = (hasIcon) ? PanelMenu.MENUITEM_LINK_WITH_ICON_CLASS : PanelMenu.MENUITEM_LINK_CLASS;

    writer.startElement("li", null);
    writer.writeAttribute("id", submenu.getClientId(), null);
    writer.writeAttribute("class", styleClass, null);
    if (style != null) {
        writer.writeAttribute("style", style, null);
    }

    writer.startElement("a", null);
    writer.writeAttribute("class", linkClass, null);

    //toggle icon
    writer.startElement("span", null);
    writer.writeAttribute("class", toggleIconClass, null);
    writer.endElement("span");

    //user icon
    if (hasIcon) {
        writer.startElement("span", null);
        writer.writeAttribute("class", "ui-icon " + icon, null);
        writer.endElement("span");
    }

    //submenu label
    writer.startElement("span", null);
    writer.writeAttribute("class", PanelMenu.MENUITEM_TEXT_CLASS, null);
    writer.writeText(submenu.getLabel(), null);
    writer.endElement("span");

    writer.endElement("a");

    //submenu children
    if (submenu.getElementsCount() > 0) {
        List<MenuElement> elements = submenu.getElements();

        writer.startElement("ul", null);
        writer.writeAttribute("class", listClass, null);

        for (MenuElement element : elements) {
            if (element.isRendered()) {
                if (element instanceof MenuItem) {
                    writer.startElement("li", null);
                    writer.writeAttribute("class", Menu.MENUITEM_CLASS, null);
                    encodeMenuItem(context, menu, (MenuItem) element);
                    writer.endElement("li");
                } else if (element instanceof Submenu) {
                    encodeDescendantSubmenu(context, menu, (Submenu) element);
                }
            }
        }

        writer.endElement("ul");
    }

    writer.endElement("li");
}
}

This is faces-config.xml

  <render-kit>
    <renderer>
        <component-family>org.primefaces.component</component-family>
        <renderer-type>org.primefaces.component.PanelMenuRenderer</renderer-type>
        <renderer-class>com.customPanelMenuRenderer</renderer-class>
    </renderer>
</render-kit>

With these codes, we made an custom renderer and we register to faces-config.xml. Last of all we should override css codes, In my situation it happens override to this class(It might be change in your project)

.ui-panelmenu .ui-panelmenu-header .ui-icon.fa{}

Finally you have a rootSubmenu with icon.