DynaForm supports facets, the autoSubmit feature, an extended view area (grid) and a client-side widget API. The examples show an advanced search form and two switchable forms rendered by the same XHTML.
An advanced dynamic form with facets, the autoSubmit feature and an extended view area (grid). The form was already submitted on page load: autoSubmit allows passing form parameters in the URL, building the form on page load and submitting it automatically.
The extended grid is closed by default; open it with the client-side API ("Show / hide advanced search"). The open / close state is kept after a postback.
Dynamic forms with labels above the fields and various elements such as the PrimeFaces divider. Click "Switch model" to switch between the two forms: the XHTML with pe:dynaForm stays the same, only the Java model changes.
<style>
.dynaform-advanced .pe-dynaform-cell input,
.dynaform-advanced .pe-dynaform-cell textarea,
.dynaform-advanced .pe-dynaform-cell[colspan="1"] input,
.dynaform-advanced .pe-dynaform-cell[colspan="1"] textarea {
width: 130px;
}
.dynaform-advanced .pe-dynaform-cell.calendar input,
.dynaform-advanced .pe-dynaform-cell[colspan="1"].calendar input {
width: 100px;
}
.dynaform-advanced .pe-dynaform-headerfacet div,
.dynaform-advanced .pe-dynaform-footerfacet div {
border: 1px dotted #808080;
padding: 10px;
text-align: center;
}
.dynaform-another .pe-dynaform-cell {
padding-bottom: 8px;
}
.dynaform-another .pe-dynaform-label {
text-align: left;
padding: 2px 20px 0 0;
}
.dynaform-another .pe-dynaform-cell.separator {
padding: 10px 0 10px 0;
}
.dynaform-another .pe-dynaform-cell.separator .separatorText {
width: 15%;
padding-left: 0;
}
.dynaform-another .p-autocomplete .p-autocomplete-dropdown {
right: -2px;
}
</style>
<div class="card dynaform-advanced">
<h5>Advanced features</h5>
<p>An advanced dynamic form with facets, the <code>autoSubmit</code> feature and an extended view area (grid). The form was already submitted on page load: <code>autoSubmit</code> allows passing form parameters in the URL, building the form on page load and submitting it automatically.
The extended grid is closed by default; open it with the client-side API ("Show / hide advanced search"). The open / close state is kept after a postback.</p>
<h:form id="formAdvancedFeatures">
<h:panelGroup id="dynaFormGroup">
<p:messages id="messages" showSummary="true"/>
<pe:dynaForm id="dynaForm" value="#{advancedDynaFormController.model}" var="data"
autoSubmit="true" buttonBarPosition="both" widgetVar="dynaFormWidgetAdvanced">
<pe:dynaFormControl styleClass="pe-dynaform-label">
<h:outputText value="#{data}"/>
</pe:dynaFormControl>
<pe:dynaFormControl type="input" for="input">
<p:inputText id="input" value="#{data.value}" required="#{data.required}"/>
</pe:dynaFormControl>
<pe:dynaFormControl type="date" for="date" styleClass="calendar">
<p:datePicker id="date" value="#{data.value}" required="#{data.required}" showIcon="true"/>
</pe:dynaFormControl>
<pe:dynaFormControl type="desc" for="desc">
<p:inputTextarea id="desc" value="#{data.value}" required="#{data.required}" autoResize="false"/>
</pe:dynaFormControl>
<f:facet name="headerRegular">
<div><h:outputText value="This is a regular header area"/></div>
</f:facet>
<f:facet name="footerRegular">
<div><h:outputText value="This is a regular footer area"/></div>
</f:facet>
<f:facet name="headerExtended">
<div><h:outputText value="This is an extended header area"/></div>
</f:facet>
<f:facet name="footerExtended">
<div><h:outputText value="This is an extended footer area"/></div>
</f:facet>
<f:facet name="buttonBar">
<p:commandButton value="Search" action="#{advancedDynaFormController.submitForm}"
process="dynaForm" update=":formAdvancedFeatures:dynaFormGroup :formAdvancedFeatures:inputValues"
oncomplete="handleCompleteAdvanced(xhr, status, args)"/>
<p:commandButton type="reset" value="Reset" style="margin-left: 5px;"/>
<p:commandButton type="button" value="Show / hide advanced search" style="margin-left: 5px;"
onclick="PF('dynaFormWidgetAdvanced').toggleExtended()"/>
</f:facet>
</pe:dynaForm>
</h:panelGroup>
<p:dialog header="Input values" widgetVar="inputValuesAdvanced">
<h:outputText value="Search has been executed with values:"/>
<p:dataList id="inputValues" value="#{advancedDynaFormController.inventoryProperties}" var="property"
style="margin:10px;">
<h:outputText value="#{property.position}: #{property.formattedValue}"
style="margin-right: 10px;"/>
</p:dataList>
</p:dialog>
</h:form>
<script>
/* <![CDATA[ */
function handleCompleteAdvanced(xhr, status, args) {
if (args && args.isValid) {
PF('inputValuesAdvanced').show();
} else {
PF('inputValuesAdvanced').hide();
}
}
/* ]]> */
</script>
</div>
<div class="card dynaform-another">
<h5>Yet another forms</h5>
<p>Dynamic forms with labels above the fields and various elements such as the PrimeFaces divider. Click "Switch model" to switch between the two forms: the XHTML with <code>pe:dynaForm</code> stays the same, only the Java model changes.</p>
<h:form id="formAnotherForms">
<p:commandLink id="switch" value="Switch model" process="switch" update="dynaFormGroup"
action="#{anotherDynaFormController.switchModel}" style="font-weight:bold;"/>
<h:panelGroup id="dynaFormGroup" layout="block" style="margin-top: 15px;">
<p:messages id="messages" showSummary="true"/>
<pe:dynaForm id="dynaForm" value="#{anotherDynaFormController.model}" var="data"
openExtended="true" widgetVar="dynaFormWidgetAnother">
<pe:dynaFormControl styleClass="pe-dynaform-label">
<h:outputText value="#{data}"/>
</pe:dynaFormControl>
<pe:dynaFormControl type="separator" styleClass="separator p-state-disabled">
<h:panelGrid columns="2" style="width:100%;" columnClasses="separatorText">
<h:outputText value="#{data}"/>
<p:divider/>
</h:panelGrid>
</pe:dynaFormControl>
<pe:dynaFormControl type="name" for="autocompl">
<p:autoComplete id="autocompl" value="#{data.value}" required="#{data.required}"
dropdown="true" completeMethod="#{anotherDynaFormController.complete}"/>
</pe:dynaFormControl>
<pe:dynaFormControl type="address" for="txt">
<p:inputText id="txt" value="#{data.value}" required="#{data.required}"/>
</pe:dynaFormControl>
<pe:dynaFormControl type="booleanchoice">
<p:selectBooleanCheckbox value="#{data.value}" required="#{data.required}"
style="vertical-align:middle;"/>
</pe:dynaFormControl>
<pe:dynaFormControl type="radiochoice">
<p:selectOneRadio value="#{data.value}" required="#{data.required}">
<f:selectItems value="#{data.selectItems}"/>
</p:selectOneRadio>
</pe:dynaFormControl>
<pe:dynaFormControl type="editor">
<p:textEditor value="#{data.value}" height="150" secure="false"/>
</pe:dynaFormControl>
<pe:dynaFormControl type="audioslider">
<h:inputHidden id="input" value="#{data.value}"/>
<h:panelGrid columns="2">
<p:slider for="input" display="output" style="width:150px;"/>
<h:outputText id="output" value="#{data.value}" style="margin-left: 5px;"/>
</h:panelGrid>
</pe:dynaFormControl>
<f:facet name="buttonBar">
<p:commandButton value="Submit" action="#{anotherDynaFormController.submitForm}"
process="dynaForm" update=":formAnotherForms:dynaFormGroup :formAnotherForms:inputValues"
oncomplete="handleCompleteAnother(xhr, status, args)"/>
<p:commandButton type="reset" value="Reset" style="margin-left: 5px;"/>
<p:commandButton type="button" value="Show / hide more fields"
rendered="#{anotherDynaFormController.model.existExtendedGrid}"
style="margin-left: 5px;" onclick="PF('dynaFormWidgetAnother').toggleExtended()"/>
</f:facet>
</pe:dynaForm>
</h:panelGroup>
<p:dialog header="Input values" widgetVar="inputValuesAnother">
<h:panelGroup id="inputValues" layout="block" style="margin:10px;">
<h:outputText value="#{anotherDynaFormController.formFields}" escape="false"/>
</h:panelGroup>
</p:dialog>
</h:form>
<script>
/* <![CDATA[ */
function handleCompleteAnother(xhr, status, args) {
if (args && args.isValid) {
PF('inputValuesAnother').show();
} else {
PF('inputValuesAnother').hide();
}
}
/* ]]> */
</script>
</div>
package org.primefaces.extensions.showcase.controller.dynaform;
import java.io.Serial;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import jakarta.annotation.PostConstruct;
import jakarta.faces.application.FacesMessage;
import jakarta.faces.context.FacesContext;
import jakarta.faces.view.ViewScoped;
import jakarta.inject.Named;
import org.primefaces.PrimeFaces;
import org.primefaces.extensions.model.dynaform.DynaFormControl;
import org.primefaces.extensions.model.dynaform.DynaFormLabel;
import org.primefaces.extensions.model.dynaform.DynaFormModel;
import org.primefaces.extensions.model.dynaform.DynaFormRow;
import org.primefaces.extensions.showcase.model.dynaform.InventoryProperty;
/**
* AdvancedDynaFormController
*
* @author Oleg Varaksin / last modified by $Author$
* @version $Revision$
*/
@Named
@ViewScoped
public class AdvancedDynaFormController implements Serializable {
@Serial
private static final long serialVersionUID = 20120423L;
private DynaFormModel model;
@PostConstruct
protected void initialize() {
model = new DynaFormModel();
// add rows, labels and editable controls
// set relationship between label and editable controls to support outputLabel
// with "for" attribute
// 1. regular row
DynaFormRow row = model.createRegularRow();
final DynaFormLabel label11 = row.addLabel("Ref. No. 1", 1, 1);
final DynaFormControl control12 = row.addControl(new InventoryProperty("(1,2)", false), "input", 1, 1);
label11.setForControl(control12);
final DynaFormLabel label13 = row.addLabel("Ref. No. 2", 1, 1);
final DynaFormControl control14 = row.addControl(new InventoryProperty("(1,4)", false), "input", 1, 1);
label13.setForControl(control14);
final DynaFormLabel label15 = row.addLabel("Ref. No. 3", 1, 1);
final DynaFormControl control16 = row.addControl(new InventoryProperty("(1,6)", false), "input", 1, 1);
label15.setForControl(control16);
// 2. regular row
row = model.createRegularRow();
final DynaFormLabel label21 = row.addLabel("Ref. No. 4", 1, 1);
final DynaFormControl control22 = row.addControl(new InventoryProperty("(2,2)", false), "input", 1, 1);
label21.setForControl(control22);
final DynaFormLabel label23 = row.addLabel("Ref. No. 5 (this field requires any not empty input)", 3, 1);
final DynaFormControl control24 = row.addControl(new InventoryProperty("(2,4)", "555-555", true), "input", 1,
1);
label23.setForControl(control24);
// 3. regular row
row = model.createRegularRow();
final DynaFormLabel label31 = row.addLabel("Date from", 1, 1);
final DynaFormControl control32 = row.addControl(new InventoryProperty("(3,2)", false), "date", 1, 1);
label31.setForControl(control32);
final DynaFormLabel label33 = row.addLabel("Date till", 1, 1);
final DynaFormControl control34 = row.addControl(new InventoryProperty("(3,4)", false), "date", 1, 1);
label33.setForControl(control34);
final DynaFormLabel label35 = row.addLabel("Expiry", 1, 1);
final DynaFormControl control36 = row.addControl(new InventoryProperty("(3,6)", new Date(), true), "date", 1,
1);
label35.setForControl(control36);
// 1. extended row
row = model.createExtendedRow();
row.addControl("Ref. No. 6", 1, 1);
row.addControl(new InventoryProperty("(4,2)", false), "input", 1, 1);
row.addControl("Ref. No. 7", 1, 1);
row.addControl(new InventoryProperty("(4,4)", false), "input", 1, 1);
row.addControl("Ref. No. 8", 1, 1);
row.addControl(new InventoryProperty("(4,6)", false), "input", 1, 1);
// 2. extended row
row = model.createExtendedRow();
row.addControl("Advanced inventory description", 2, 1);
row.addControl(new InventoryProperty("(5,2)", false), "desc", 4, 1);
}
public DynaFormModel getModel() {
return model;
}
public List<InventoryProperty> getInventoryProperties() {
if (model == null) {
return null;
}
final List<InventoryProperty> inventoryProperties = new ArrayList<InventoryProperty>();
for (final DynaFormControl dynaFormControl : model.getControls()) {
if (dynaFormControl.getData() instanceof InventoryProperty) {
inventoryProperties.add((InventoryProperty) dynaFormControl.getData());
}
}
return inventoryProperties;
}
public String submitForm() {
final FacesMessage.Severity sev = FacesContext.getCurrentInstance().getMaximumSeverity();
final boolean hasErrors = sev != null && FacesMessage.SEVERITY_ERROR.compareTo(sev) >= 0;
PrimeFaces.current().ajax().addCallbackParam("isValid", !hasErrors);
return null;
}
}
package org.primefaces.extensions.showcase.controller.dynaform;
import java.io.Serial;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import jakarta.faces.application.FacesMessage;
import jakarta.faces.context.FacesContext;
import jakarta.faces.model.SelectItem;
import jakarta.faces.view.ViewScoped;
import jakarta.inject.Named;
import org.apache.commons.lang3.StringUtils;
import org.primefaces.PrimeFaces;
import org.primefaces.extensions.model.dynaform.DynaFormControl;
import org.primefaces.extensions.model.dynaform.DynaFormLabel;
import org.primefaces.extensions.model.dynaform.DynaFormModel;
import org.primefaces.extensions.model.dynaform.DynaFormRow;
import org.primefaces.extensions.showcase.model.dynaform.FormField;
/**
* AnotherDynaFormController
*
* @author Oleg Varaksin / last modified by $Author$
* @version $Revision$
*/
@Named
@ViewScoped
public class AnotherDynaFormController implements Serializable {
@Serial
private static final long serialVersionUID = 20120423L;
private DynaFormModel modelOne;
private DynaFormModel modelTwo;
private boolean showModelOne = true;
public DynaFormModel getModel() {
return showModelOne ? getModelOne() : getModelTwo();
}
public DynaFormModel getModelOne() {
if (modelOne != null) {
return modelOne;
}
modelOne = new DynaFormModel();
// add rows, labels and editable controls
// set relationship between label and editable controls to support outputLabel
// with "for" attribute
// 1. regular row
DynaFormRow row = modelOne.createRegularRow();
final DynaFormLabel label11 = row.addLabel("Short Name", 1, 1);
final DynaFormLabel label12 = row.addLabel("Street", 2, 1);
// 2. regular row
row = modelOne.createRegularRow();
final DynaFormControl control21 = row.addControl(new FormField(true), "name", 1, 1);
final DynaFormControl control22 = row.addControl(new FormField(false), "address", 2, 1);
label11.setForControl(control21);
label12.setForControl(control22);
// 3. regular row
row = modelOne.createRegularRow();
final DynaFormLabel label31 = row.addLabel("Long Name", 1, 1);
final DynaFormLabel label32 = row.addLabel("Zip code, city", 2, 1);
// 4. regular row
row = modelOne.createRegularRow();
final DynaFormControl control41 = row.addControl(new FormField(true), "name", 1, 1);
final DynaFormControl control42 = row.addControl(new FormField(false), "address", 2, 1);
label31.setForControl(control41);
label32.setForControl(control42);
// 5. regular row
row = modelOne.createRegularRow();
row.addControl("Make choice", "separator", 3, 1);
// 6. regular row
row = modelOne.createRegularRow();
row.addControl("PrimeFaces fan?", 1, 1);
row.addControl("Married?", 1, 1);
row.addControl("Children", 1, 1);
// 7. regular row
row = modelOne.createRegularRow();
final List<SelectItem> pffan = new ArrayList<SelectItem>();
pffan.add(new SelectItem("Sure", "Sure"));
pffan.add(new SelectItem("Don't know", "Don't know"));
row.addControl(new FormField("Sure", false, pffan), "radiochoice", 1, 1);
row.addControl(new FormField(false, false), "booleanchoice", 1, 1);
final List<SelectItem> children = new ArrayList<SelectItem>();
children.add(new SelectItem("No", "No"));
children.add(new SelectItem("1", "1"));
children.add(new SelectItem("2", "2"));
children.add(new SelectItem("More", "More"));
row.addControl(new FormField("No", false, children), "radiochoice", 1, 1);
// 1. extended row
row = modelOne.createExtendedRow();
row.addControl("Notes", 3, 1);
// 2. extended row
row = modelOne.createExtendedRow();
row.addControl(new FormField("Hallo DynaForm!", false), "editor", 3, 1);
return modelOne;
}
public DynaFormModel getModelTwo() {
if (modelTwo != null) {
return modelTwo;
}
modelTwo = new DynaFormModel();
// add rows, labels and editable controls
// set relationship between label and editable controls to support outputLabel
// with "for" attribute
// 1. regular row
DynaFormRow row = modelTwo.createRegularRow();
row.addControl("Audio Analog Output Volume", "separator", 3, 1);
// 2. regular row
row = modelTwo.createRegularRow();
row.addControl("Port 1", 1, 1);
row.addControl("Port 2", 1, 1);
row.addControl("Port 3", 1, 1);
// 3. regular row
row = modelTwo.createRegularRow();
row.addControl(new FormField(60, false), "audioslider", 1, 1);
row.addControl(new FormField(0, false), "audioslider", 1, 1);
row.addControl(new FormField(0, false), "audioslider", 1, 1);
// 4. regular row
row = modelTwo.createRegularRow();
row.addControl("Audio Digital Output Volume", "separator", 3, 1);
// 5. regular row
row = modelTwo.createRegularRow();
row.addControl("Port 4", 1, 1);
row.addControl("Port 5", 1, 1);
row.addControl("Port 6", 1, 1);
// 6. regular row
row = modelTwo.createRegularRow();
row.addControl(new FormField(10, false), "audioslider", 1, 1);
row.addControl(new FormField(50, false), "audioslider", 1, 1);
row.addControl(new FormField(50, false), "audioslider", 1, 1);
// 7. regular row
row = modelTwo.createRegularRow();
row.addControl("HDMI Output Volume", "separator", 3, 1);
// 8. regular row
row = modelTwo.createRegularRow();
row.addControl("Port 1", 1, 1);
row.addControl("Port 2", 1, 1);
row.addControl("Port 3", 1, 1);
// 9. regular row
row = modelTwo.createRegularRow();
row.addControl(new FormField(20, false), "audioslider", 1, 1);
row.addControl(new FormField(80, false), "audioslider", 1, 1);
row.addControl(new FormField(40, false), "audioslider", 1, 1);
return modelTwo;
}
public String switchModel() {
showModelOne = !showModelOne;
// reset models (simulate new loading)
if (showModelOne) {
modelOne = null;
}
else {
modelTwo = null;
}
return null;
}
public List<String> complete(final String query) {
final List<String> results = new ArrayList<String>();
char letter;
for (letter = 'a'; letter <= 'm'; letter++) {
results.add(query + letter);
}
return results;
}
public String getFormFields() {
final DynaFormModel model = showModelOne ? getModelOne() : getModelTwo();
if (model == null) {
return null;
}
final StringBuilder sb = new StringBuilder();
for (final DynaFormControl dynaFormControl : model.getControls()) {
if (dynaFormControl.getData() instanceof FormField) {
final FormField ff = (FormField) dynaFormControl.getData();
if (ff.getValue() != null && StringUtils.isNotBlank(ff.getValue().toString())) {
sb.append(ff.getValue());
sb.append("<br/>");
}
}
}
return sb.toString();
}
public String submitForm() {
final FacesMessage.Severity sev = FacesContext.getCurrentInstance().getMaximumSeverity();
final boolean hasErrors = sev != null && FacesMessage.SEVERITY_ERROR.compareTo(sev) >= 0;
PrimeFaces.current().ajax().addCallbackParam("isValid", !hasErrors);
return null;
}
}