0 Replies Latest reply on Aug 15, 2008 3:28 AM by Matt Davis

    Dynamic form element help

    Matt Davis Newbie

      I could use some help figuring out how to let a user add an arbitrary number of elements to an existing form. I know this isn't really seam-specific, but I'm sure one of you has done something like this in the past.


      I have a large form, and one of the sections lets the user add an arbitrary number of degrees, sort of like you would on a job application.


      I need some kind of subform within the main form that lets them click a button to add a new row of form elements where they can fill in the next degree's information.


      Advice on how to do this would be really helpful.


      Here's my first hack at it, that doesn't really work, but you can get the idea.


      This is part of the xhtml page. I copied a portion of my large form:
      I used a4j repeat to repeat a table row for each degree in a degreeSet. I'm only displaying the degree name for now.


      <a4j:outputPanel id="table">
        <table border="1" class="dr-table rich-table">
          <thead class="dr-table-thead">
            <tr class="dr-table-header rich-table-header">
              <th class="dr-table-headercell rich-table-headercell"><h:outputText value="Degree" /></th>
             </tr>
          </thead>
          <tbody>
           <a4j:repeat value="#{degreeSet.degrees}" var="curDegree" binding="#{updateBean.repeater}">
             <tr>
               <td>
                 <h:outputText value="#{curDegree.degreeName}" />
               </td>     
             </tr>
           </a4j:repeat>
          </tbody>
        </table>
      </a4j:outputPanel>
              
      <h:inputText value="#{degree.degreeName}" size="7"></h:inputText>
      <rich:messages />
      <h:panelGrid>
        <h:commandButton value="Add Degree" action="#{degreeSet.addDegree(degree)}"  />
      </h:panelGrid>
      



      This is the update bean that I got from the Richfaces a4j:repeat section. I don't really understand what it is doing. In the original example it populated a dropdown box when the user entered data in another field...  but anyway, the a4j:repeat element still uses it for its repeater element.


      UpdateBean.java
      
      import javax.faces.component.html.HtmlInputText;
      import javax.faces.context.FacesContext;
      import org.ajax4jsf.component.UIRepeat;
      import org.jboss.seam.annotations.Name;
      
      import java.util.HashSet;
      import java.util.Set;
      
      @Name("updateBean")
      public class UpdateBean {
      
          HtmlInputText priceRef;
          private UIRepeat repeater;
          private Set<Integer> keys = null;
          
          /**
           * @return the keys
           */
          public Set getKeys() {
              return keys;
          }
      
          /**
           * @param keys the keys to set
           */
          public void setKeys(Set keys) {
              this.keys = keys;
          }
      
          public void setRepeater(UIRepeat repeater) {
              this.repeater = repeater;
          }
      
          public UIRepeat getRepeater() {
              return repeater;
          }
      
          public HtmlInputText getPriceRef() {
              return priceRef;
          }
      
          public void setPriceRef(HtmlInputText priceRef) {
              this.priceRef = priceRef;
          }
          
          public String change(){
              
              HashSet keys = new HashSet<Integer>();
              int rowKey = getRepeater().getRowIndex();
              keys.add(rowKey);
              setKeys(keys);
              priceRef.processValidators(FacesContext.getCurrentInstance());
              priceRef.processUpdates(FacesContext.getCurrentInstance());
              return null;
          }
      }
      



      This is a class that holds an ArrayList of degrees.  I have this funky addDegree that takes an object so it can accept a degreejavaassist$3  whatever object. I know this is wrong, but eh, I tried.


      import java.util.ArrayList;
      
      import org.jboss.seam.annotations.Name;
      
      @Name("degreeSet")
      public class DegreeSet {
           
           private ArrayList<Degree> degrees = new ArrayList<Degree>();
      
           public DegreeSet(){
                Degree d = new Degree();
                d.setDegreeName("testDegree");
                degrees.add(d);
           }
           
           public void addDegree(Object degreeIn){
                if(degreeIn instanceof Degree){
                     degrees.add((Degree)degreeIn);
                }
                else return;
           }
           
           public void addDegree(Degree degreeIn){
                degrees.add(degreeIn);
           }
           
           public ArrayList<Degree> getDegrees() {
                return degrees;
           }
      
           public void setDegrees(ArrayList<Degree> degrees) {
                this.degrees = degrees;
           }
           
      }
      



      The degree class... just a bunch of strings really.


      import java.util.Date;
      
      import org.jboss.seam.annotations.Name;
      
      @Name("degree")
      public class Degree {
           
           private String degreeName;
           private String discipline;
           private String department;
           private String institution;
           private String country;
           private Date startDate;
           private Date endDate;
           
           public String getDegreeName() {
                return degreeName;
           }
           public void setDegreeName(String degreeName) {
                this.degreeName = degreeName;
           }
           public String getDiscipline() {
                return discipline;
           }
           public void setDiscipline(String discipline) {
                this.discipline = discipline;
           }
           public String getDepartment() {
                return department;
           }
           public void setDepartment(String department) {
                this.department = department;
           }
           public String getInstitution() {
                return institution;
           }
           public void setInstitution(String institution) {
                this.institution = institution;
           }
           public String getCountry() {
                return country;
           }
           public void setCountry(String country) {
                this.country = country;
           }
           public Date getStartDate() {
                return startDate;
           }
           public void setStartDate(Date startDate) {
                this.startDate = startDate;
           }
           public Date getEndDate() {
                return endDate;
           }
           public void setEndDate(Date endDate) {
                this.endDate = endDate;
           }
      
      }
      
      



      Thanks!