12 Replies Latest reply on Sep 17, 2011 3:03 AM by okanxyz

    Generating menu items inside <rich:contextMenu> dynamically

    chandru.in

      Hi,

      Could some one please point out the problem in the following page code?

      <%@ page language="java" contentType="text/html; charset=ISO-8859-1"
       pageEncoding="ISO-8859-1"%>
      
      <%@taglib uri="http://java.sun.com/jsf/core" prefix="f"%>
      <%@taglib uri="http://java.sun.com/jsf/html" prefix="h"%>
      <%@taglib uri="http://richfaces.org/a4j" prefix="a4j"%>
      <%@taglib uri="http://richfaces.org/rich" prefix="rich"%>
      <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
      <html>
      <head>
      <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
      <title>Demo Page</title>
      </head>
      <body>
      <f:view>
       <h:form>
       <a4j:outputPanel layout="block" id="demoPanel"
       style="width: 100px; height: 100px; border: 1px solid black">
       </a4j:outputPanel>
       <rich:contextMenu>
       <rich:menuItem value="Demo" />
       <a4j:repeat var="currentDestination"
       value="#{dataContainer.destinations}">
       <rich:menuItem value="Re-Load for #{currentDestination}" />
       </a4j:repeat>
       </rich:contextMenu>
       </h:form>
      </f:view>
      </body>
      </html>


      The statically generated item with title "Demo" is shown fine. But the dynamically generated ones are not. Can't we use a4j:repeat inside contextMenu? If not then how to dynamically generate the menu items?

        • 1. Re: Generating menu items inside <rich:contextMenu> dynamica
          chandru.in

          Any hint??

          • 2. Re: Generating menu items inside <rich:contextMenu> dynamica
            ilya_shaikovsky

            you should not use not a4j nor ui repeat components. Use c:forEach instead or use component binding.

            • 3. Re: Generating menu items inside <rich:contextMenu> dynamica
              chandru.in

              Could you kindly explain why that approach does not work?

              Also, component binding seems like an over kill as it is needed at just one place. I read at many places that using JSTL along with JSF is not advisable.

              Could you please enlighten me on these?

              • 4. Re: Generating menu items inside <rich:contextMenu> dynamica
                ilya_shaikovsky

                1) c:forEach will works fine in facelets envirenment.

                http://www.ilikespam.com/blog/c:foreach-vs-ui:repeat-in-facelets - the difference.

                if you do not using facelets - use binding.

                • 5. Re: Generating menu items inside <rich:contextMenu> dynamica
                  chandru.in

                  I managed it quite a bit with component binding. Thanks for the tip.

                  I have set up the actionExpression for each individual HtmlMenuItem component. The action method is invoked which I verify with a System.out.println(); statement.

                  Here is the code used to build the ContextMenu object.

                  public ContextMenu getPopupMenu() {
                   popupMenu = new ContextMenu();
                   List<HtmlMenuItem> components = new ArrayList<HtmlMenuItem>();
                  
                   for (String string : destinations) {
                   HtmlMenuItem item = new HtmlMenuItem();
                   item.setValue(string);
                   MethodExpression expression = FacesContext.getCurrentInstance()
                   .getApplication().getExpressionFactory()
                   .createMethodExpression(
                   FacesContext.getCurrentInstance().getELContext(),
                   "#{dataContainer.show}", null, new Class<?>[0]);
                   item.setActionExpression(expression);
                   components.add(item);
                   }
                   popupMenu.getChildren().clear();
                   popupMenu.getChildren().addAll(components);
                   return popupMenu;
                   }


                  popupMenu is an instance reference.

                  But how do I determined which menu item was selected in the action method? Also, what is the reason for a4j:repeat not working inside context menu while it works perfectly inside components like a4j:outputPanel?

                  • 6. Re: Generating menu items inside <rich:contextMenu> dynamica
                    ilya_shaikovsky

                    "But how do I determined which menu item was selected in the action method?"

                    add parameters or use actionListener instead.

                    • 7. Re: Generating menu items inside <rich:contextMenu> dynamica
                      chandru.in

                      Thanks that worked really well using ActionListener!

                      Could you please enlighten me on the reason for a4j:repeat not working inside context menu while it works perfectly inside components like a4j:outputPanel?

                      I have tried searching a lot but not getting any hint. :(

                      • 8. Re: Generating menu items inside <rich:contextMenu> dynamica
                        liuliu

                        hi,

                        i want to create a contextmenu dynamically for every line of a datatable. I used the code posted by chandru.in to creat the contextmenu. the xhtml is like this

                        <rich:dataTable var="line" value="#{list}">
                         <rich:column>
                         <t:graphicImage id="imgAction" value="#{line.actionImg}" />
                         <rich:contextMenu binding="#{line.lineContextMenu}" />
                         </rich:column>
                        </rich:dataTable>
                        


                        But i get a error like this:

                        binding="#{line.lineContextMenu}": Target Unreachable, identifier 'line' resolved to null


                        i want to know if we can use the contextmenu in this way?

                        Thanks in advance



                        • 9. Re: Generating menu items inside <rich:contextMenu> dynamica
                          ilya_shaikovsky

                          and what is inside your bean? have you initialized this variable?

                          • 10. Re: Generating menu items inside <rich:contextMenu> dynamica
                            liuliu

                            yes. i initialized this variable.

                            if i replace the binding of rich:contextMenu with value , like

                            <rich:contextMenu value="#{line.lineContextMenu}" />


                            there is no exception, but contextmenu does not work simply.

                            if i use
                            <h:outputText value="#{line.lineContextMenu}" />


                            I can see the object is created.

                            in the bean, i have the code is almost the same as the code of chandru.in shown above.

                            • 11. Re: Generating menu items inside <rich:contextMenu> dynamica
                              fesi

                              Hi

                               

                              I have the same problem as Iiumin Hu.

                               

                              I would like to create a rich:contextMenu within each row of a rich:dataTable. The menu items of the context menu must be added dynamically (i.e. each row has different context menu entries).

                               

                              This leads to a dilemma:

                              Dynamically adding menu items to a context menu is not possible using ui:repeat/a4j:repeat because rich:contextMenu only accepts rich:menuItem or rich:menuGroup as its children. Using c:forEach is not possible neither, because we are whithin a rich:dataTable and each row will have a different number of menu items within its context menu (i.e. different number of components in the component tree).

                               

                              So I hoped the solution is to use the binding attribute of rich:contextMenu. But like Iiumin Hu, I get a an Exception telling me, that the element I use as binding target is unreachable:

                              javax.faces.FacesException: javax.el.PropertyNotFoundException: /path/to/my/page.xhtml binding="#{_row.contextMenu}": Target Unreachable, identifier '_row' resolved to null

                               

                              The relevant parts of the page look like this:

                              <rich:dataTable ... var="_row" ...>

                                   <rich:column>

                                        <f:facet name="header>...</f:facet>

                                        <rich:contextMenu ... submitMode="ajax" binding="#{_row.contextMenu}" />

                                   </rich:column>

                              ...

                              </rich:dataTable>

                               

                              Is there anybody having successfully resolved this problem?

                              • 12. Re: Generating menu items inside <rich:contextMenu> dynamica
                                okanxyz

                                I have a same problem like Felix and liumin hu, but with dropdown menu.

                                When i remove column with menu it's renders fine, but when i put column back with <rich:dropDownMenu binding="#{item.menu}" it show a same exception from above.

                                This is mine method generating dropdown menu object in backing bean:

                                private void generateMenu()

                                {

                                        menu = new UIDropDownMenu();

                                        menu.setDirection(Positioning.bottomRight);

                                        menu.setMode(Mode.server);

                                        menu.setJointPoint(Positioning.topRight);                   

                                        menu.setId("menuOdsjek" + odsjek.getId());

                                        menu.setStyle("padding:0px;white-space: normal;");

                                        HtmlCommandLink link = new HtmlCommandLink();

                                        link.setTitle("Otvori stranicu odsjeka");

                                        HtmlOutputText text = new HtmlOutputText();

                                        text.setValue(odsjek.getNazivAt());

                                        link.getChildren().add(text);

                                        link.setId("linkOdsjek" + odsjek.getId());

                                        FacesComponentFunkcije.addAction(link, "#{odsjeciForm.otvoriOdsjek}");

                                        link.setStyle("font-size:11px;");

                                        menu.getFacets().put("label", link);

                                }