Dynamic Field Addition in Enterprise Forms HST Component at Runtime

Overview

You can add fields, field groups, or pages to an Enterprise Forms HST Component dynamically at runtime. This allows you to modify the form structure based on user input, session data, or other runtime conditions, without explicitly defining these elements in the form document.

Override specific methods in your HST component to inject additional fields or groups as needed.

Example: Dynamic Field Creation

The Enterprise Forms Demo project demonstrates how to add fields dynamically at runtime.

To test this scenario:

  1. Build and run the Enterprise Forms Demo. You need access to the Bloomreach Content Maven repository.
  2. Navigate to http://localhost:8080/site/dynamicfields.
  3. Complete all form fields and submit the form.
  4. Review the stored data in the Form Data application in the CMS.
  5. Visit http://localhost:8080/site/dynamicfields?region=us (note the region parameter).
  6. Confirm that an additional field named "State" appears before the postal code field.
  7. Complete all fields and submit the form.
  8. Review the stored data in the Form Data application in the CMS again.
  9. Verify that the "State" field value is present for the second submission.

The associated form document does not define a "State" field. The field is added at runtime in the HST component.

The following example (site/components/src/main/java/com/onehippo/cms7/eforms/demo/components/DynamicFieldsEformComponent.java) shows how to override the parse(final FormBean bean, ...) method to add a field dynamically:

/** * DynamicFieldsEformComponent demonstrates adding an extra field at runtime when the form document does not define it. * * This example adds a "State" field if the URL contains the query parameter "region=US". */ public class DynamicFieldsEformComponent extends FormStoringEformComponent { @Override protected Form parse(final FormBean bean, final FormContext formContext, final HstRequest request) { Form form = FormFieldFactory.createForm(bean, formContext, null, request); if (isStateFieldNecessary(request)) { final TextField stateField = createStateTextField(form); // Register the field so the form can store and retrieve its value form.registerField(stateField); // Insert the state field at the desired position on the first page form.getPages().get(0).addField(3, stateField); } return form; } /** * Determines whether the "State" field should be shown. * Returns true if the request contains the query parameter "region=US". */ private boolean isStateFieldNecessary(final HstRequest request) { String region = getPublicRequestParameter(request, "region"); return (StringUtils.equalsIgnoreCase("US", region)); } /** * Creates a required "State" text field at runtime. */ private TextField createStateTextField(final Form form) { TextField stateTextField = TextField.builder(form, "state") .label("State") .length(40) .mandatory(true) .minLength(1) .maxLength(40).build(); return stateTextField; } }

The parse(final FormBean bean, ...) method is called when rendering the form (doBeforeRender()) and when processing submissions (doAction()). In this example, the method checks for a specific request parameter to determine whether to add the extra field. You can extend this logic to use other criteria as needed.

You can create field instances as shown in createStateTextField(), or extend existing field implementations for more complex requirements.

Example: Dynamic Field Group and Page Creation

You can also add field groups and pages dynamically at runtime. The demo form at http://localhost:8080/site/dynamicregistration illustrates this capability.

To test dynamic field group and page creation:

  1. Visit http://localhost:8080/site/dynamicregistration.
  2. Complete all form fields and submit the form.
  3. Review the stored data in the Form Data application in the CMS.
  4. Visit http://localhost:8080/site/dynamicregistration?people=4 (note the people parameter).
  5. Confirm that the form displays multiple pages, one for each person.
  6. Complete all fields and submit the form.
  7. Review the stored data in the Form Data application in the CMS again.
  8. Verify that the information for all registering people is present for the second submission.

The following example (site/components/src/main/java/com/onehippo/cms7/eforms/demo/components/DynamicRegistrationEformComponent.java) shows how to override the parse(FormBean, FormContext, HstRequest) method to add groups and pages dynamically:

/** * DynamicRegistrationEformComponent demonstrates adding extra fields, groups, and pages at runtime when the form document does not define them. * * This example adds one page per registering person if the URL contains the query parameter "people=$number", e.g. "people=3". */ public class DynamicRegistrationEformComponent extends FormStoringEformComponent { private static Logger log = LoggerFactory.getLogger(DynamicRegistrationEformComponent.class); @Override protected Form parse(final FormBean bean, final FormContext formContext, final HstRequest request) { Form form = super.parse(bean, formContext, request); long numberOfPeople = getRegisteringPeople(request); if (numberOfPeople > 0) { for(int i = 0; i < numberOfPeople; i++) { final String name = String.format("person-%d", i + 1); final String label = String.format("Person %d", i + 1); FieldGroup contactFieldGroup = createContactFieldGroup(form, name, label); Page page = new Page(label); page.addField(contactFieldGroup); form.getPages().add(page); } } return form; } private long getRegisteringPeople(final HstRequest request) { String numberOfPeopleValue = getPublicRequestParameter(request, "people"); return StringUtils.isNotEmpty(numberOfPeopleValue) ? Long.parseLong(numberOfPeopleValue) : 0; } private FieldGroup createContactFieldGroup(final Form form, final String name, final String label) { FieldGroup fieldGroup = FieldGroup.builder(form, name, name).label(label).build(); form.registerFieldGroup(fieldGroup); String[][] fieldNames = { {"name", "Name"}, {"email", "Email"}, {"street-addr", "Street Address"}, {"city", "City"}, {"postal-code", "Postal code"} }; for(String[] fieldName : fieldNames) { TextField field = TextField.builder(form, fieldName[0]) .label(fieldName[1]) .length(40) .minLength(1) .maxLength(40) .build(); // Add the new field to the group before registering it with the form fieldGroup.addField(field); form.registerField(field); } DateField dobField = DateField.builder(form, "dob") .label("Date of Birth") .dateFormat("dd/MM/yyyy") .build(); fieldGroup.addField(2, dobField); form.registerField(dobField); String[] genderValues = {"male", "female", "other"}; String[] genderDisplayValues = {"Male", "Female", "Unspecified"}; AbstractField genderField = RadioGroup.builder(form, "gender", Arrays.asList(genderValues)) .displayValues(Arrays.asList(genderDisplayValues)) .label("Gender") .hint("Select your gender") .build(); fieldGroup.addField(3, genderField); form.registerField(genderField); return fieldGroup; } }

This component adds one page per person, each containing a field group with personal information fields. The number of pages is determined by the people query parameter.

Summary

  • Override the parse method in your HST component to add fields, field groups, or pages dynamically at runtime.
  • Use request parameters or other runtime data to control which fields or groups are added.
  • Register new fields and groups with the form to ensure correct storage and retrieval.
  • Refer to the demo project for practical implementation examples.
Share Feedback
Page: /build/enterprise-plugins/enterprise-forms/dynamic-field-addition-at-runtime
Section: Build
Category *