Custom Form Fields

Enterprise Forms allows you to define custom form field types. This guide describes the required components to add a custom "password field" to your project. You can use the same approach to add other custom fields. This example assumes your project is named "My Project" and uses the JCR namespace "myproject".

Add the Field Definition to the CMS Content CND File

Define the JCR node type for your custom form field in your project's namespace. Update the CND file located in the repository-data-application module.

At the top of the CND file, declare the Enterprise Forms 'eforms' namespace:

<eforms='http://www.onehippo.org/jcr/eforms/nt/1.0'>

At the bottom of the CND file, add the new node type:

[myproject:passwordfield] > eforms:textfield
- myproject:length (long) = "40" autocreated

Create the Field Model in the CMS Module

Add a model class for the new form field in your CMS module:

import javax.jcr.RepositoryException; import org.hippoecm.frontend.model.JcrNodeModel; import com.onehippo.cms7.eforms.cms.model.AbstractFieldModel; public class PasswordFieldModel extends AbstractFieldModel { private long length; public PasswordFieldModel(JcrNodeModel nodeModel) throws RepositoryException { super(nodeModel); } @Override public String getFieldType() { return "password"; } public long getLength() { return length; } public void setLength(final long length) { this.length = length; } }

Create the Field Panel for the Drag and Drop Area

Implement a Wicket panel for the drag and drop area of the form editor. Add this class to your CMS module:

import org.apache.wicket.behavior.AttributeAppender; import org.apache.wicket.markup.head.CssHeaderItem; import org.apache.wicket.markup.head.IHeaderResponse; import org.apache.wicket.markup.html.IHeaderContributor; import org.apache.wicket.markup.html.form.PasswordTextField; import org.apache.wicket.model.Model; import org.apache.wicket.request.resource.CssResourceReference; import org.apache.wicket.request.resource.ResourceReference; import com.onehippo.cms7.eforms.cms.model.AbstractFieldModel; import com.onehippo.cms7.eforms.cms.panels.AbstractFieldPanel; public class PasswordFieldPanel extends AbstractFieldPanel implements IHeaderContributor { private static final ResourceReference PASSWORD_CSS = new CssResourceReference(PasswordFieldPanel.class, "PasswordFieldPanel.css"); public PasswordFieldPanel(String id, AbstractFieldModel fieldModel) { super(id, fieldModel); PasswordFieldModel model = (PasswordFieldModel) fieldModel; PasswordTextField textField = new PasswordTextField("field"); textField.add(new AttributeAppender("size", new Model(model.getLength()), " ")); textField.setEnabled(false); add(textField); } @Override public void renderHead(final IHeaderResponse response) { response.render(CssHeaderItem.forReference(PASSWORD_CSS)); } }

Add the corresponding HTML file PasswordFieldPanel.html to the same Java package:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd" xml:lang="en" lang="en"> <wicket:extend> <input type="password" class="textfield" wicket:id="field"/> </wicket:extend> </html>

To apply custom styling, add a CSS file named PasswordFieldPanel.css to the same package.

Create a Properties Panel for the CMS

Implement a Wicket properties panel for editing the field's properties. Add this class to your CMS module:

import javax.jcr.RepositoryException; import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.ajax.form.OnChangeAjaxBehavior; import org.apache.wicket.markup.html.basic.Label; import org.apache.wicket.markup.html.form.TextField; import org.apache.wicket.model.StringResourceModel; import com.onehippo.cms7.eforms.cms.form.FormPlugin; import com.onehippo.cms7.eforms.cms.model.AbstractFieldModel; import com.onehippo.cms7.eforms.cms.model.SingleValuePropertyModel; import com.onehippo.cms7.eforms.cms.properties.panels.AbstractFieldPropertiesPanel; public class PasswordFieldPropertiesPanel extends AbstractFieldPropertiesPanel { public PasswordFieldPropertiesPanel(final String id, final FormPlugin formPlugin, final AbstractFieldModel fieldModel) throws RepositoryException { super(id, formPlugin, fieldModel); Label lengthLabel = new Label("length", new StringResourceModel("password.length", this, null)); TextField<String> lengthField = new TextField<String>("length-field", new SingleValuePropertyModel<String>( fieldModel.getNodeModel(), "myproject:length")); lengthField.add(new OnChangeAjaxBehavior() { @Override protected void onUpdate(AjaxRequestTarget target) { target.add(formPlugin); } }); add(lengthLabel); add(lengthField); } }

Add the corresponding HTML file PasswordFieldPropertiesPanel.html to the same package:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd" xml:lang="en" lang="en"> <wicket:extend> <div class="property length"> <span class="label" wicket:id="length">[HINT]</span><br/> <input type="text" wicket:id="length-field"/> </div> </wicket:extend> </html>

Add the properties file PasswordFieldPropertiesPanel.properties to the same package:

field.type.password=Password
password.length=Render Size 

Implement the Field Interface on the CMS Side

Implement the Field interface for your custom form field. This class provides access to all field-related classes and metadata. Add this class to your CMS module:

import org.apache.wicket.request.resource.PackageResourceReference; import org.apache.wicket.request.resource.ResourceReference; import com.onehippo.cms7.eforms.cms.fields.Field; import com.onehippo.cms7.eforms.cms.model.AbstractFieldModel; import com.onehippo.cms7.eforms.cms.panels.AbstractFieldPanel; import com.onehippo.cms7.eforms.cms.properties.panels.AbstractFieldPropertiesPanel; public class PasswordField implements Field { @Override public String getId() { return "password"; } @Override public String getName() { return "Password Field"; } @Override public String getNodeName() { return "myproject:passwordfield"; } @Override public ResourceReference getIcon() { return new PackageResourceReference(PasswordField.class, "password.png"); } @Override public Class<? extends AbstractFieldModel> getModel() { return PasswordFieldModel.class; } @Override public Class<? extends AbstractFieldPanel> getPanel() { return PasswordFieldPanel.class; } @Override public Class<? extends AbstractFieldPropertiesPanel> getPropertiesPanel() { return PasswordFieldPropertiesPanel.class; } }

To display an icon for the new field in the picker, add a file named password.png to the same package.

Update the CMS pom.xml to Include Field Resources

Ensure that the field resources are packaged by updating the <build> section of your CMS module's pom.xml:

<resources> <resource> <filtering>false</filtering> <directory>${basedir}/src/main/java</directory> <includes> <include>**/*.html</include> <include>**/*.css</include> <include>**/*.png</include> <include>**/*.gif</include> <include>**/*.js</include> <include>**/*.properties</include> </includes> </resource> <resource> <filtering>false</filtering> <directory>${basedir}/src/main/resources</directory> </resource> </resources>

Register the Field in the Enterprise Forms Plugin Configuration

Add the new form field to the Enterprise Forms configuration in the repository. Update the YAML definition in your project's repository-data-application module:

definitions: config: /hippo:namespaces/eforms/form/editor:templates/_default_/root/cluster.options: field.include: [com.example.fields.PasswordField]

Create a Bean for the Field in the Site Module

Implement a bean for the field in your site module:

import org.hippoecm.hst.content.beans.Node; import com.onehippo.cms7.eforms.hst.beans.AbstractFieldBean; import com.onehippo.cms7.eforms.hst.beans.FieldType; @Node(jcrType = "myproject:passwordfield") public class PasswordFieldBean extends AbstractFieldBean { public Long getLength() { final Long length = getProperty("myproject:length"); if (length == null) { return 0L; } return length; } @Override public FieldType getType() { return FieldType.TEXT; } }

Add the package to the hst-beans-annotated-classes context parameter in web.xml:

<context-param> <param-name>hst-beans-annotated-classes</param-name> <param-value> classpath*:org/onehippo/**/*.class ,classpath*:com/onehippo/**/*.class ,classpath*:com/example/common/beans/**/*.class </param-value> </context-param>

Create a Field for the Site Module

Implement the field class for the site module:

import com.example.common.beans.PasswordFieldBean; import com.onehippo.cms7.eforms.hst.model.AbstractField; import com.onehippo.cms7.eforms.hst.model.Form; public class PasswordField extends AbstractField { private Long length; public PasswordField(PasswordFieldBean bean, Form form) { super(bean, form); this.length = bean.getLength(); } public long getLength() { return length; } @Override public String toString() { final StringBuilder sb = new StringBuilder(); sb.append("PasswordField"); sb.append("{length=").append(length); sb.append('}'); return sb.toString(); } }

Add the Field to the Form's JSP Template

Update the form's JSP template (eformsrenderfield.tag) to render the password field. Use the field's getType() to determine its type. Example:

<c:when test="${field.type eq 'passwordfield'}"> <div class="eforms-field"> <label><c:out value='${field.label}'/><span class="eforms-req"><c:out value='${field.requiredMarker}'/></span></label> <input type="password" name="${field.formRelativeUniqueName}" class="${field.styleClass}" <c:if test='${field.length gt 0}'>size="${field.length}"</c:if> /> <span class="eforms-hint"><c:out value='${field.hint}'/></span> </div> </c:when>

Summary

To add a custom form field to Enterprise Forms:

  1. Define the field type in the CND file.
  2. Implement the field's model, panel, and properties panel in the CMS module.
  3. Register the field in the Enterprise Forms configuration.
  4. Add the corresponding bean and field implementation in the site module.
  5. Update the JSP template to render the field.

Follow this pattern to implement additional custom field types as needed.

Share Feedback
Page: /build/enterprise-plugins/enterprise-forms/custom-form-fields
Section: Build
Category *
Custom form fields | Bloomreach Content Documentation