I have been trying to get a dynamic menu to work and am having a lot of difficulty. I am using the JSF-RI 1.2, Facelets, SEAM and Tomahawk. I know this method is not necessarily the standard method of using JSF, but up till now it has worked well for me. To give you an idea of what is going on I have an application with two independent modules now that have seam observers on them that register the modules with the profileComponentModule Class. Then the following code gets the registered  components and calls a method that allows each module to dynamically build and add the appropriate menu options to the menu based on the authenticated user's roles.

The menu is generated and displays as I would expect, but the when the user clicks one of the menu options the actionlisteners' attributes are always 'null,' which causes the action that is called to fail. Both the action listener and the action are being called, but it appears that the state is not being appropriately restored.

The ProfileApplicationMenu Class is in the session scope and the constructor that does the work follows.

   public ProfileApplicationMenu() throws DAOException {
      HtmlPanelNavigationMenu lMenu = new HtmlPanelNavigationMenu();

      /* Add the Application Menus */
      Collection<String> lApplicationModuleNames =
              ProfileComponentModule.getApplicationModuleNames();
      for( String lApplicationModuleName : lApplicationModuleNames) {
         ProfileApplicationModule lApplicationModule =
                (ProfileApplicationModule) Component.getInstance(lApplicationModuleName);
         lApplicationModule.addMenuContents(lMenu);
      }
      menu = lMenu;
   }

The StudentService Module Class has the following code:

   public void addMenuContents(HtmlPanelNavigationMenu aPanelNavigationMenu)
        throws DAOException {

      if (isUser()) {
         UINavigationMenuItem lStudentInformationMenu = new UINavigationMenuItem();
         lStudentInformationMenu.setItemLabel("Student Information");
         lStudentInformationMenu.setId("studentInfo");

         aPanelNavigationMenu.getChildren().add(lStudentInformationMenu);
         lStudentInformationMenu.setParent(aPanelNavigationMenu);

         populateStudents();

         if (studentInformationManager.isStudent() && students.size() == 1) {
            for (Student lStudent : students) {
               addStudentMenuItems(lStudentInformationMenu, lStudent);
            }
         } else {
            for (Student lStudent : students) {
               addStudentMenu(lStudentInformationMenu, lStudent);
            }
         }
      }
   }

   private void addStudentMenu(UINavigationMenuItem aMenu, Student aStudent) {
      String lStudentName = aStudent.getFirstName() + " " + aStudent.getLastName();
      UINavigationMenuItem lStudentMenu = new UINavigationMenuItem();
      lStudentMenu.setItemLabel(lStudentName);
      lStudentMenu.setId(aStudent.getUsername());

      aMenu.getChildren().add( lStudentMenu);
      lStudentMenu.setParent(aMenu);

      addStudentMenuItems(lStudentMenu, aStudent);
   }
    
   private void addStudentMenuItems(UINavigationMenuItem aMenu, Student aStudent) {

      buildMenuItem( aMenu, "General Information", aStudent, "generalInformation");
      buildMenuItem( aMenu, "Contacts",            aStudent, "contacts");
      buildMenuItem( aMenu, "Attendance",          aStudent, "attendance");
      buildMenuItem( aMenu, "Schedule",            aStudent, "schedule");
      buildMenuItem( aMenu, "Grades",              aStudent, "grades");

   }

   private void buildMenuItem( UINavigationMenuItem aMenu,
                               String aLabel,
                               Student aStudent,
                               String aDisplayMode) {

      UINavigationMenuItem lMenuItem = new UINavigationMenuItem();
      lMenuItem.setItemLabel(aLabel);
      lMenuItem.setId(aStudent.getUsername() + "_" + aDisplayMode);
      lMenuItem.getAttributes().put("student", aStudent);
      lMenuItem.getAttributes().put("displayMode", aDisplayMode);

      addEventHandlers(lMenuItem);

      aMenu.getChildren().add(lMenuItem);
      lMenuItem.setParent(aMenu);

   }

I guess I don't know what I am doing wrong as when I debug this the attributes get set on the MenuItems, but it must be failing to restore the data as they are null when the actionListener and action are called.




On Aug 14, 2008, at 9:05 AM, Eivind Ronnevik wrote:

Chad,

 

Sorry for my mistake, the NavigationMenuItem does not extend UIComponent. I was a bit fast there, not giving it a proper thought. ;)

 

But as you say, there is a UINavigationMenuItem which does. I did a try locally, and realized that you also have to create the HtmlPanelNavigationMenu java side (set componentBinding), as a list of UINavigationMenuItems will give you an argument mismatch exception if you try to point to it from the t:navigationMenuItems.
But if you add this list to the panel with getChildren().add()-method, it works J

 

This would be the setter of my panel property:

 

public void setPanel(HtmlPanelNavigationMenu panel)
      {
            panel.getChildren().clear();

           

            UIParameter parameter = new UIParameter();
            parameter.setId("param1");
            parameter.setName("yourName");
            parameter.setValue("yourValue");

           

            UINavigationMenuItem item = new UINavigationMenuItem();
            item.setId("MenuItem1");
            item.getChildren().add(parameter);
            item.setItemLabel("MenuLabel");

           

            try
            {
                  Class[] parameterList = { Class.forName("javax.faces.event.ActionEvent") };
                  MethodBinding actionListenerBinding = FacesContext.getCurrentInstance().getApplication().createMethodBinding(
                        "#{test.myListener}",parameterList);
                  item.setActionListener(actionListenerBinding);
            }
            catch (Exception e) {

                 

            }          

           

            MethodBinding methodBinding = FacesContext.getCurrentInstance().getApplication().createMethodBinding(
                        "#{test.myAction}",null);

                 

            item.setAction(methodBinding);

           

            List<UINavigationMenuItem> list = new ArrayList<UINavigationMenuItem>();
            list.add(item);

           

            panel.getChildren().addAll(list);

           

            this.panel = panel;
      }

 

 

Only thing is that there seems to be a problem with firing off the actions/actionListeners on the UINavigationMenuItem (http://issues.apache.org/jira/browse/TOMAHAWK-238). I tried a bit and couldn’t get it working, and I’m in a bit of a hurry now, but it might be a starting point for you at least J

 

Regards,

 

Eivind

 

 

From: Chad Skinner [mailto:chadws@sbcglobal.net] 
Sent: 14. august 2008 14:31
To: MyFaces Discussion
Subject: Re: PanelNavigation2

 

Is the example incorrect then? The example uses NavigationMenuItem which extends the Model object and not UIComponent. I don't believe that it has a getChildren method, but rather only an add(NavigationMenuItem) method. Hense my problem figuring out how to add attributes or parameters to it. I was just looking at the 1.7 snapshot docs and there is a a UINavigationMenuItem, should this be used in place of NavigationMenuItem?

 

 

 

On Aug 14, 2008, at 6:07 AM, Eivind Ronnevik wrote:

 

Chad,

 

I guess you can use the UIParameter object:

 

 

UIParameter parameter = new UIParameter();
parameter.setName(“yourName”);
parameter.setValue(“theValue”);

 

In your loop you would then add this to the lItem
lItem.getChildren().add(parameter);

 

And then you look it up in your ActionListener method like this:

 

FacesContext context = FacesContext.getCurrentInstance();
Map map = context.getExternalContext().getRequestParameterMap();
String key = (String) map.get("yourName ");

 

Regards,

 

Eivind

 

 

From: Chad Skinner [mailto:cws-dls@sbcglobal.net] 
Sent: 14. august 2008 04:35
To: MyFaces Discussion
Subject: PanelNavigation2

 

I am trying to create a dynamic PanelNavigation Menu using the method utilized in the examples. The problem I am having is that I need my actionListener to be able to access an attribute that identifies the current item and I don't see how to add an attribute to the NavigationMenuItem.

 

For example, I have the facelet code:

 

<t:panelNavigation2 id="profileNavigation"
                    layout="list"
                    itemClass="mypage"
                    activeItemClass="selected"
                    disabledStyle="color:red">
   <t:navigationMenuItems id="navitems" value="#{mybean.menuItems}" />
</t:panelNavigation2>

 

 

 

My Bean contains the following Code similar to the following as I have removed a lot of the code to simplify the example:

 

List<NavigationMenuItems> lMenuItems = new ArrayList<NavigationMenuItem>();
for( Student lStudent : students ) {
   NavigationMenuItem lItem = new NavigationMenuItem( lStudent.getName(), "#{myaction}");
   lItem.setActionListener("#{myActionListener}");
   lItem.setValue(lStudent.getName())
}

 

The problem is that when the user clicks on the menu Item the action listener needs access to two pieces of information: 1) the student and 2) a display mode.

 

Can anyone tell me what I need to do to set attributes on the components so that I can look them up in the actionListener.