Dynamic forms, JSF world was long waiting for

The new PrimeFaces Extensions release 0.5.0 brought a new DynaForm component. Normally, we can build a form quite straightforward by h:panelGrid oder p:panelGrid if the count of rows / columns, positions of elements, etc. are known. That’s true for static forms. But it’s not possible to use h:panelGrid oder p:panelGrid if a form is described dynamically, at runtime. E.g. if the entire form’s definition is placed in a database or a XML file. DynaForm makes possible to build a dynamic form with labels, inputs, selects and any other elements by model. There aren’t limitations. Explore all its features in the showcase. Let’s show how to build a simple dynamic form.

Main steps:
Create model instance: DynaFormModel model = new DynaFormModel();
Add row to regular grid: DynaFormRow row = model.createRegularRow();
Add label: DynaFormLabel label = row.addLabel(value, colspan, rowspan);
Add editable control: DynaFormControl control = row.addControl(data, type, colspan, rowspan);
Set relationship between label and control (optional): label.setForControl(control);

Repeat four last steps as many times as needed. What is could look like from UI point of view? A screenshot after a failed form validation:

The main tag is pe:dynaForm. Child tag pe:dynaFormControl matches created in Java controls by ” type” attribute. This is usually a “one to many” relation. XHTML / Java (controller bean and model) code to the dynamic form above is listed below.

<h:panelGroup id="dynaFormGroup">
    <p:messages id="messages" showSummary="true"/>

    <pe:dynaForm id="dynaForm" value="#{dynaFormController.model}" var="data">
        <pe:dynaFormControl type="input" for="txt">
            <p:inputText id="txt" value="#{data.value}" required="#{data.required}"/>
        </pe:dynaFormControl>
        <pe:dynaFormControl type="calendar" for="cal" styleClass="calendar">
            <p:calendar id="cal" value="#{data.value}" required="#{data.required}" showOn="button"/>
        </pe:dynaFormControl>
        <pe:dynaFormControl type="select" for="sel" styleClass="select">
            <p:selectOneMenu id="sel" value="#{data.value}" required="#{data.required}">
                <f:selectItems value="#{dynaFormController.languages}"/>
            </p:selectOneMenu>
        </pe:dynaFormControl>
        <pe:dynaFormControl type="textarea" for="tarea">
            <p:inputTextarea id="tarea" value="#{data.value}" required="#{data.required}" autoResize="false"/>
        </pe:dynaFormControl>
        <pe:dynaFormControl type="rating" for="rat">
            <p:rating id="rat" value="#{data.value}" required="#{data.required}"/>
        </pe:dynaFormControl>

        <f:facet name="buttonBar">
            <p:commandButton value="Submit" action="#{dynaFormController.submitForm}"
                             process="dynaForm" update="_mainForm_dynaFormGroup"/>
            <p:commandButton type="reset" value="Reset" style="margin-left: 5px;"/>
        </f:facet>
    </pe:dynaForm>
</h:panelGroup>
@ManagedBean
@ViewScoped
public class DynaFormController implements Serializable {

   private DynaFormModel model;

   private static List<SelectItem> LANGUAGES = new ArrayList<SelectItem>();

   public DynaFormController() {
      model = new DynaFormModel();

      // add rows, labels and editable controls
      // set relationship between label and editable controls to support outputLabel with "for" attribute

      // 1. row
      DynaFormRow row = model.createRegularRow();

      DynaFormLabel label11 = row.addLabel("Author", 1, 1);
      DynaFormControl control12 = row.addControl(new BookProperty("Author", true), "input", 1, 1);
      label11.setForControl(control12);

      DynaFormLabel label13 = row.addLabel("ISBN", 1, 1);
      DynaFormControl control14 = row.addControl(new BookProperty("ISBN", true), "input", 1, 1);
      label13.setForControl(control14);

      // 2. row
      row = model.createRegularRow();

      DynaFormLabel label21 = row.addLabel("Title", 1, 1);
      DynaFormControl control22 = row.addControl(new BookProperty("Title", false), "input", 3, 1);
      label21.setForControl(control22);

      // 3. row
      row = model.createRegularRow();

      DynaFormLabel label31 = row.addLabel("Publisher", 1, 1);
      DynaFormControl control32 = row.addControl(new BookProperty("Publisher", false), "input", 1, 1);
      label31.setForControl(control32);

      DynaFormLabel label33 = row.addLabel("Published on", 1, 1);
      DynaFormControl control34 = row.addControl(new BookProperty("Published on", false), "calendar", 1, 1);
      label33.setForControl(control34);

      // 4. row
      row = model.createRegularRow();

      DynaFormLabel label41 = row.addLabel("Language", 1, 1);
      DynaFormControl control42 = row.addControl(new BookProperty("Language", false), "select", 1, 1);
      label41.setForControl(control42);

      DynaFormLabel label43 = row.addLabel("Description", 1, 2);
      DynaFormControl control44 = row.addControl(new BookProperty("Description", false), "textarea", 1, 2);
      label43.setForControl(control44);

      // 5. row
      row = model.createRegularRow();

      DynaFormLabel label51 = row.addLabel("Rating", 1, 1);
      DynaFormControl control52 = row.addControl(new BookProperty("Rating", 3, true), "rating", 1, 1);
      label51.setForControl(control52);
    }

    public DynaFormModel getModel() {
        return model;
    }

    public String submitForm() {
        ... // do something
    }

    public List<SelectItem> getLanguages() {
        if (LANGUAGES.isEmpty()) {
            LANGUAGES.add(new SelectItem("en", "English"));
            LANGUAGES.add(new SelectItem("de", "German"));
            LANGUAGES.add(new SelectItem("ru", "Russian"));
            LANGUAGES.add(new SelectItem("tr", "Turkish"));
        }

        return LANGUAGES;
    }
}

public class BookProperty implements Serializable {

    private String name;
    private Object value;
    private boolean required;

    public BookProperty(String name, boolean required) {
        this.name = name;
        this.required = required;
    }

    public BookProperty(String name, Object value, boolean required) {
        this.name = name;
        this.value = value;
        this.required = required;
    }

    // getter // setter
}
You see that one of important features is a buil-in support for labels. DynaForm renders labels automatically – no need to write p:outputLabel. Another feature is autoSubmit flag. It allows pass form parameters in URL, build a form on page load and submit it automatically. More highlights: expandable extended view area (grid), open / close state saving, widget’s client-side API, various facets. Next screenshots demonstrate how to build dynamic forms with lables above fields and various elements like PrimeFaces separator. Two forms in this example are switched by clicking on the “Switch model” link. Note, XHTML code with pe:dynaForm stays the same, only Java model gets changed.

Explore the corresponding code in the use case Yet another forms.

Reference: Dynamic forms, JSF world was long waiting for from our JCG partner Oleg Varaksin at the Thoughts on software development blog.

Related Whitepaper:

Functional Programming in Java: Harnessing the Power of Java 8 Lambda Expressions

Get ready to program in a whole new way!

Functional Programming in Java will help you quickly get on top of the new, essential Java 8 language features and the functional style that will change and improve your code. This short, targeted book will help you make the paradigm shift from the old imperative way to a less error-prone, more elegant, and concise coding style that’s also a breeze to parallelize. You’ll explore the syntax and semantics of lambda expressions, method and constructor references, and functional interfaces. You’ll design and write applications better using the new standards in Java 8 and the JDK.

Get it Now!  

One Response to "Dynamic forms, JSF world was long waiting for"

  1. Majid says:

    Hi,
    I was looking for a tutorial to learn JSF , then I found this blog, could you please post the source code so I can try it.
    thanks lot, your help is appreciated.

Leave a Reply


8 − eight =



Java Code Geeks and all content copyright © 2010-2014, Exelixis Media Ltd | Terms of Use | Privacy Policy
All trademarks and registered trademarks appearing on Java Code Geeks are the property of their respective owners.
Java is a trademark or registered trademark of Oracle Corporation in the United States and other countries.
Java Code Geeks is not connected to Oracle Corporation and is not sponsored by Oracle Corporation.

Sign up for our Newsletter

20,709 insiders are already enjoying weekly updates and complimentary whitepapers! Join them now to gain exclusive access to the latest news in the Java world, as well as insights about Android, Scala, Groovy and other related technologies.

As an extra bonus, by joining you will get our brand new e-books, published by Java Code Geeks and their JCG partners for your reading pleasure! Enter your info and stay on top of things,

  • Fresh trends
  • Cases and examples
  • Research and insights
  • Two complimentary e-books