2 Replies Latest reply on Jun 24, 2010 5:52 AM by elenaveretilo

    How to select one item and immediately fullfill the form with item data?

    elenaveretilo

      Hi all!

       

      I need your brilliant minds agian. Can I select one item with <h:selectOneMenu> (or any other selectors) , and after that use this item in the form?

      More explanation: I want to select the item in selectoneitem, and after that I get immidiately full filling the form with item ( in my case user ) data. Can I do it? If yes - how?


      My code:

       <ui:composition xmlns="http://www.w3.org/1999/xhtml"
                      xmlns:ui="http://java.sun.com/jsf/facelets"
                      xmlns:a4j="http://richfaces.org/a4j"
                      xmlns:rich="http://richfaces.org/rich"
                      xmlns:h="http://java.sun.com/jsf/html"
                      xmlns:f="http://java.sun.com/jsf/core"
                      xmlns:fc="http://www.fusioncharts.com"
                      xmlns:t="http://myfaces.apache.org/tomahawk"
                      template="template.xhtml">
           <ui:define name="title">Save user page</ui:define>
           <ui:define name="content">
           
                <h:selectOneMenu value="#{saveUserBean.user}" style="width: 200px;">
                     <f:selectItems value="#{saveUserBean.companyUsers}"/>
                </h:selectOneMenu>
                <br/><br/><br/>                         
                                         
                <h:form id="saveUserForm">
                     <h:outputText value="Add or update user"/><br/><br/><br/>
                     <div style="width: 300px;">
                          <table width="100%" cellpadding="5" cellspacing="5">
                              <tr>
                                   <td>
                                        <h:selectOneMenu value="#{saveUserBean.user}" style="width: 200px;">
                                              <f:selectItems value="#{saveUserBean.companyUsers}"/>
                                         </h:selectOneMenu>
                                   </td>
                              </tr>
                               <tr>
                                    <td width="1">
                                         User name:
                                    </td>
                                    <td>
                                         <h:inputText id="userName" value="#{saveUserBean.user.name}" style="width: 100%;" required="true" />
                                    </td>
                               </tr>
                               <tr>
                                    <td valign="top" nowrap="nowrap">
                                         User password:
                                    </td>
                                    <td>
                                         <h:inputSecret value="#{saveUserBean.password}" style="width: 100%;" required="true" />
                                    </td>
                               </tr>
                                 <tr>
                                    <td nowrap="nowrap">
                                         User role:
                                    </td>
                                    <td>
                                         <h:selectOneMenu value="#{saveUserBean.role}" style="width: 200px;">
                                              <f:selectItems value="#{saveUserBean.roles}"/>
                                         </h:selectOneMenu>
                                    </td>
                               </tr>
                          </table><br/>
                          <center>
                               <h:commandButton value="Save user" action="#{saveUserBean.saveUser}" style="width: 40%;"/>
                               <a4j:commandButton ajaxSingle="true" value="Clear" actionListener="#{saveUserBean.clear}" style="width: 40%;" reRender="saveUserForm"/>
                          </center>
                     </div>
                </h:form>
      
           </ui:define>
      </ui:composition>
      

       

       

       

      package no.sfront.saveuser;
      
      import java.util.List;
      
      import javax.faces.application.FacesMessage;
      import javax.faces.context.FacesContext;
      import javax.faces.event.ActionEvent;
      import javax.faces.model.SelectItem;
      
      import no.sfront.login.SessionBean;
      import no.sfront.torque.generated.User;
      
      /**
        * @author Elena Veretilo
        * 
        */
      
      public class SaveUserBean 
      {
           private String username;
           private String password;
           private int role;
           private User user;
           private List<SelectItem> roles;
           private List<SelectItem> companyUsers;
           
           // Constructor
           public SaveUserBean() 
           {
                SaveUserUtils saveUserUtils = SaveUserUtils.getInstance();
                companyUsers = saveUserUtils.createCompanyUsersList();
                roles = saveUserUtils.createRolesList();
           }
           
           public static SaveUserBean getInstance() {
                FacesContext facesContext = FacesContext.getCurrentInstance();
      
                return (SaveUserBean) facesContext.getApplication()
                          .getELResolver().getValue(facesContext.getELContext(), null,
                                    "saveUserBean");
           } 
            
           public String saveUser()
           {
                this.createUser();
                return "main";
           }
            
           private String createUser() 
           {
                FacesContext context = FacesContext.getCurrentInstance();
                String username = this.getUsername().trim();
                
                boolean userExists = SaveUserUtils.getInstance().userExists(username);
      
                if (userExists) 
                {
                     FacesMessage message = new FacesMessage("User with such name already exists. Please select another name.");
                     context.addMessage(null, message);
                } 
                else 
                {
                     String password = this.getPassword().trim();
                     int role = this.getRole();
                     
                     // TODO get companyId from session as attribute
                     int companyId = 1; // SessionBean.getInstance().getCompanyId();
                
                     // may return created user and then we add it to companyUsers!!!!!!!!!!!11               
                     User user = SaveUserUtils.getInstance().createAndInsertUser(username, password, role, companyId);
                     
                     SelectItem item = new SelectItem();
                     item.setValue(user.getId());
                     item.setLabel(user.getName());
                     this.companyUsers.add(item);
                }
      
                return null;
           }
           
           private String updateUser() 
           {
                return null;
           }
           
           public void clear(ActionEvent event)
           {
                this.setUsername("");
                this.setPassword("");
                this.setRole(-1);
           }
           
           public String getUsername() {
                return username;
           }
           
           public void setUsername(String username) {
                this.username = username;
           }
           
           public String getPassword() {
                return password;
           }
           
           public void setPassword(String password) {
                this.password = password;
           }
           
           public int getRole() {
                return role;
           }
           
           public void setRole(int role) {
                this.role = role;
           }
           
           public List<SelectItem> getRoles() {
                return roles;
           }
      
           public void setRoles(List<SelectItem> roles) {
                this.roles = roles;
           }
           
           public List<SelectItem> getCompanyUsers() {
                return companyUsers;
           }
           
           public void setCompanyUsers(List<SelectItem> companyUsers) {
                this.companyUsers = companyUsers;
           }
           
           public User getUser() {
                System.out.println("get user = " + (user == null));
                return user;
           }
      
           public void setUser(User user) {
                System.out.println("set user = " + (user == null));
                this.user = user;
           }  
      }
      
      
      

       

       

      Maybe I need first convert the selectedItem to user class? Or maybe something else?

       


      Please help!

       

      With best wishes!

       

       

        • 1. Re: How to select one item and immediately fullfill the form with item data?
          akaine

          Feeling generous today...

           

          1. Add <a4j:keepAlive beanName="saveUserBean"/> at the top of the content section. This will prevent your updated data from the bean to be lost in ajax requests.

           

          2. Write a converter class that would convert Object to String and viceversa and declare it in faces-config:

          import javax.faces.component.UIComponent;
          import javax.faces.component.UISelectItems;
          import javax.faces.context.FacesContext;
          import javax.faces.convert.Converter;
          import javax.faces.model.SelectItem;
          
          public class MyConverter implements Converter {
          
              public MyConverter() {
              }
          
              public Object getAsObject(FacesContext facesContext, UIComponent uiComponent, String s) {
                  List<SelectItem> items = retrieveSelectItems(uiComponent);
                  if (items != null) {
                      for (SelectItem item : items) {
                          if (item.getLabel().equals(s)){
                              return item.getValue();
                          }
                      }
                  }
                  return s;
              }
          
              public String getAsString(FacesContext facesContext, UIComponent uiComponent, Object value) {
          
                  List<SelectItem> items = retrieveSelectItems(uiComponent);
                  if (items != null) {
                      for (SelectItem item : items) {
                          if (item.getValue().equals(value)){
                              return item.getLabel();
                          }
                      }
                  }
                  return value == null ? null : "";
              }
          
              @SuppressWarnings("unchecked")
              private List<SelectItem> retrieveSelectItems(UIComponent uiComponent) {
                  List<SelectItem> items = null;
                  if (!uiComponent.getChildren().isEmpty() && uiComponent.getChildren().get(0) instanceof UISelectItems) {
                      items = (List<SelectItem>)((UISelectItems)uiComponent.getChildren().get(0)).getValue();
                  }
                  return items;
              }
          }
          

           

          Add List<SelectItem> companyUsersSI with respective getter and setter to the backing bean and fill with the data from the database or whatever:

           

          for(User user : companyUsers){
              companyUsersSI.add(new SelectItem(user,user.getName()));
              //the first param of the constructor should be Object (can be some id or the object itself),
              //the second param should be of type String with the text that will be shown in the select list
          }
          

           

          3. Add a converter and a valueChangeListener to the main selector (you can use rich:comboBox instead of h:selectOneMenu, or you can leave it as it is, the resulting htmls are almost the same). Here's an example of comboBox:

          <rich:comboBox id="someid" value="#{saveUserBean.selectedUser}" defaultLabel="Select a value" width="200" valueChangeListener="#{saveUserBean.loadSelectedUser}" converter="myConverter">
             <f:selectItems value="#{saveUserBean.companyUsersSI}" />
             <a4j:support ajaxSingle="true" event="onselect" reRender="saveUserForm" />
          </rich:comboBox>
          

           

          4. Add the method for the valueChangeListener (for ex. "loadSelectedUser") to the backing bean where you fill your selected user object with needed data:

          public void loadSelectedUser(ValueChangeEvent event){
              user = (User)event.getNewValue();
          }
          

           

          I strongly recommend to use userId instead of user object directly for the SelectItem list initialization to decrease the data traveling through ajax requests = faster updates, less errors. In this case change the loadSelectedUser method to make the appropriate cast and necessary operations to fill the user object.

          ---------------------------------------------------------------------------------------

           

          Now the explanation of how this works:

          - the managed bean is loaded as soon as you load the page

          - by the time the form is loaded you should fill the SelectItem list, use class constructor or the method you call to load the page (2nd option is better)

          - the converter will be executed automatically and switch all objects with strings you've assigned, so the select field will contain readable text labels

          - when you select a user from the list the converter will be executed again switching the object values back, so when it comes to the method defined in valueChangeListener the event parameter is filled with the switched value from the selected SelectItem so you may cast it and do whatever you want with it; in this case - fill the user object which is used to display selected user data

          - since the comboBox contains a4j:support with the defined event, after the method from valueChangeListener is executed the data on the page gets partially rerendered. The rerendering scope is defined in the reRender attribute. As a result you will see the filled form without any visible page reaload.

           

           

          Hope this helps, google for more if needed...

          • 2. Re: How to select one item and immediately fullfill the form with item data?
            elenaveretilo

            Hi all! Sorry for being away for long time)

             

            Akaine Harga, thanks - your suggestion is greate. I did as you said: add converter, set to item value user id (not user object), add valueChangeListener. And also didnt use saveUserBean.user.name - decided that its the best practice.

             

            Here is my code (maybe it will be helpfull for somebody):

             

             

             

             

             

            // My valueChangeListener     public void loadSelectedUser(ValueChangeEvent event){
                      Integer id = (Integer)event.getNewValue(); 
                      User tempUser = SaveUserUtils.getInstance().getUserById(id);
                       
                      this.setUsername(tempUser.getName());
                      this.setPassword(tempUser.getPassword());
                      this.setRole(tempUser.getRoleType());
                 }
            
            
            
            // My converter
            public class SaveUserConverter implements Converter {
             
                public SaveUserConverter() {
                }
             
                public Object getAsObject(FacesContext facesContext, UIComponent uiComponent, String s) {
                    List<SelectItem> items = this.retrieveSelectItems(uiComponent);
                    if (items != null) {
                        for (SelectItem item : items) {
                            if (item.getLabel().equals(s)){
                                return item.getValue();
                            }
                        }
                    }
                    return s;
                }
             
                public String getAsString(FacesContext facesContext, UIComponent uiComponent, Object value) {
                    List<SelectItem> items = this.retrieveSelectItems(uiComponent);
                    if (items != null) {
                        for (SelectItem item : items) {
                            if (item.getValue().equals(value)){
                                 return item.getLabel();
                            }
                        }
                    }
                    return value == null ? null : "";
                }
             
                @SuppressWarnings("unchecked")
                private List<SelectItem> retrieveSelectItems(UIComponent uiComponent) {
                    List<SelectItem> items = null;
                    if (!uiComponent.getChildren().isEmpty() && uiComponent.getChildren().get(0) instanceof UISelectItems) {
                        items = (List<SelectItem>)((UISelectItems)uiComponent.getChildren().get(0)).getValue();
                    }
                    return items;
                }
            }
            
            
            
            // My creation of selectItems - note: I am using item.setValue(user.getId()) instead of item.setValue(user);
                 public List<SelectItem> createCompanyUsersList() 
                 {
                      List<SelectItem> companyUsers = new ArrayList<SelectItem>();
                      
                      try {
                           // TODO get companyId from session as attribute
                           int companyId = 1; // SessionBean.getInstance().getCompanyId();
                           Criteria criteria = new Criteria();
                           criteria.add(CompanyPeer.ID, companyId);
                           
                           List<User> users = UserPeer.doSelect(new Criteria());               
                           for (int i = 0; i < users.size(); i++) {
                                SelectItem item = new SelectItem();
                                User user = users.get(i);
                                item.setValue(user.getId());
                                item.setLabel(user.getName());
                                companyUsers.add(item);
                           }
                      } catch (TorqueException e) {
                           throw new RuntimeException(e);
                      }
                      
                      return companyUsers;
                 }