Skip to main content
Skip table of contents

Forms module changes

Overview

In the scope of the 8.0.0 release we've introduced several major breaking changes in the forms module of the itextcore repository.

List of breaking changes:

  • Form fields with the same fully qualified names are now merged with each other.

    • If these fields have a different field type, value or default value, a log will be displayed (in the reading mode or when reading the document) or an exception will be thrown (in cases when the user tries to add a field with the same name as an already existing one, but different /FT, /V or /DV values). Merge occurs when an acroform is created, when children are added to a field, when field is renamed, or when fields are added to an acroform. 
      PdfAcroForm.addField(PdfFormField, PdfPage, boolean) can be used to not throw an exception while adding a new field.

    • setValue method sets the value not only to the field setValue is called on, but also to its siblings (children of the parent field) if they have the same fully qualified name. Such fields may present when it was not possible to merge them, or, for example, during acroform reading.

    • If there are 2 fields in the hierarchy of fields – a parent without /T entry and a child, and the child has all the values in its dictionary (except for /Parent and /Kids) that match the parent values, and child /Kids contain only annotations (no form fields), then this child will be merged with the parent, that is, the /Kids of the child will become the /Kids of the parent. This makes the document structure cleaner (field annotations become pure widgets). Parent should not have /T entry because we only want to perform such a merge if the field doesn't contain any name (even an empty one).
      For radio groups, all of its child form fields are merged with it, since radio group should contain only annotation children according to the specification. This means that we force radio buttons to be pure widgets in order to match the PDF specification.

    • For fields with multiple widgets, all annotations are added to the page (previously only fields with one widget were supported).

  • PdfFormField.setValue doesn't set the value to the child form fields any longer.

  • PdfAcroForm.replaceFieldfields now get replaced in their parents, where previously they just would have been added to the main form dictionary.

  • Fields (including merged fields) that do not have /T key are considered fields named "" (empty string). 

    Changed PdfFormField logic to be able to add fields without partial name. In general we leave the field without changes and treat it's name as an empty string. This name is handled as any other name, since an empty string is still a string (e.g. fields merging, search, remove, etc...). Full name for field's children looks like rootFieldName.parentFieldName.childName In this particular case parentFieldName will be an empty string. This behavior violates the PDF 2.0 specification, but it is valid for PDF 1.7.

  • Moved radio button, push button, checkbox, text field drawing logic from forms to renderers.

    • This led to some changes in the fields appearance, and now flattened and interactive fields are drawn in almost the same way.

    • Also fixed a bug related to fields stream data: it was written to the content stream of the page before, but now it is in the field normal appearance which is used for drawing the annotation.

    • Creating fields using model element became much more convenient. Currently we have two main ways to create form field in the acroform structure:

      1. First one is the old one: through the usage of PdfAcroForm class.

      2. Second one is much less complicated and easy for users. One needs to simply create a layout element related to form fields and add it to the Document object like we usually do for other layout elements (such as Paragraph, Table, Div, etc...). After that, the form field will be automatically placed on the page and related elements will be added to the acroform if iterative mode is enabled. This is not yet supported for choice form fields.

    • Text form field drawing logic was moved to TextAreaRenderer and InputFieldRenderer.

      • Text drawing was moved to the related layout elements.

      • Text approximation is improved.

      • Border drawing bug with border being 2 times smaller was fixed.

      • Text no longer overlaps the border.

    • Some new classes were added for checkboxes drawing:

      /form/renderer/checkboximpl/HtmlCheckBoxRenderingStrategy.java

      /form/renderer/checkboximpl/ICheckBoxRenderingStrategy.java

      /form/renderer/checkboximpl/PdfACheckBoxRenderingStrategy.java

      /form/renderer/checkboximpl/PdfCheckBoxRenderingStrategy.java

  • Model element can be passed to PdfFormAnnotation by using public PdfFormAnnotation setFormFieldElement(IFormField element). Note that annotation properties will take precedence, so such properties cannot be overridden by using this method (e.g. background, text color, etc.), but it can be useful to take into account when drawing those properties that the annotation does not have (e.g. paddings). Also note that the model element won't be used for annotations for choice form fields.

  • Each model element is responsible for one annotation. We can add them to the document using Document.add method. Elements with the same id will be responsible for the annotations of the field with the name equal to id. Note that fields with the same fully qualified field name shall have the same field type, value, and default value to merge it without problems.
    Re-adding the same model element two or more times can lead to an undefined behavior since model element properties is changed in PdfFormAnnotation.

API changes:

Breaking change

Upgrade path

Created builder classes for every different PdfFormField implementation instead of static creator methods in PdfFormField class:

com.itextpdf.forms.fields.CheckBoxFormFieldBuilder.java

com.itextpdf.forms.fields.ChoiceFormFieldBuilder.java

com.itextpdf.forms.fields.PushButtonFormFieldBuilder.java

com.itextpdf.forms.fields.RadioFormFieldBuilder.java

com.itextpdf.forms.fields.SignatureFormFieldBuilder.java

com.itextpdf.forms.fields.TextFormFieldBuilder.java

com.itextpdf.forms.fields.FormFieldBuilder.java

com.itextpdf.forms.fields.NonTerminalFormFieldBuilder.java

com.itextpdf.forms.fields.TerminalFormFieldBuilder.java

Use builders instead of old creator methods and set appropriate properties, e.g. instead of

JAVA
PdfFormField.createText(pdfDoc, new Rectangle(100, 600, 200, 30), 
"Name", "Enter your name")

use

JAVA
PdfTextFormField textField = new TextFormFieldBuilder(pdfDoc, "Name")
.setWidgetRectangle(new Rectangle(100, 600, 200, 30))
.createText();
textField.setValue("Enter your name");

PdfAcroForm started to store only its direct children instead of all descending form fields (and every form field stores its kids). This affected every operation related to fields management (add, remove, get), so
public Map<String, PdfFormField> getFormFields() usage should be replaced either by
public Map<String, PdfFormField> getRootFormFields() or getAllFormFields() that were added to PdfAcroForm, and some convenient methods related to child fields were added in PdfFormField.

Use getRootFormFields() for getting all root fields (i.e. direct children of Acroform dictionary) or getAllFormFields() for getting all descending fields (including the children of the children).

PdfFormField class was split onto PdfFormField and PdfFormAnnotation. Methods related to widget annotations used from form fields were moved to PdfFormAnnotation:

setPage, setBackgroundColor, setRotation, setAction, setVisibility, setBorderWidth, setBorderColor, setBorderStyle, setAppearance.

A few convenience getters were added into PdfFormField:

getChildFormAnnotations, getFirstFormAnnotation. They can be used to reach child annotations.

First use getFirstFormAnnotation or getChildFormAnnotations of PdfFormField and then call the corresponding method.

Generating appearance was moved from PdfFormField to PdfFormAnnotation class. Some of them were also renamed:

  • drawRadioAppearance to drawRadioButtonAndSaveAppearance

  • drawTextAppearance, drawMultiLineTextAppearance to drawTextFormFieldAndSaveAppearance

  • drawPushButtonAppearance to drawPushButtonFieldAndSaveAppearance

  • drawCheckAppearance, drawPdfA2CheckAppearance to drawCheckBoxAndSaveAppearance

If you used to override some drawing methods in PdfFormField, from now on you have to subclass PdfFormAnnotation and override the corresponding drawing methods.

PdfFormAnnotation.drawRadioButtonAndSaveAppearance have to be overridden iso PdfFormField.drawRadioAppearance.

Model element classes and corresponding renderers were moved from html2pdf to forms module:

/form/element/AbstractSelectField.java

/form/element/Button.java (InputButton is merged with Button)

/form/element/CheckBox.java

/form/element/ComboBoxField.java

/form/element/FormField.java

/form/element/IFormField.java

/form/element/InputField.java

/form/element/IPlaceholderable.java

/form/element/ListBoxField.java

/form/element/Radio.java

/form/element/TextArea.java

/form/renderer/AbstractFormFieldRenderer.java

/form/renderer/AbstractOneLineTextFieldRenderer.java

/form/renderer/AbstractSelectFieldRenderer.java

/form/renderer/AbstractTextFieldRenderer.java

/form/renderer/ButtonRenderer.java (InputButtonRenderer is merged with ButtonRenderer)

/form/renderer/CheckBoxRenderer.java

/form/renderer/InputFieldRenderer.java

/form/renderer/RadioRenderer.java

/form/renderer/SelectFieldComboBoxRenderer.java

/form/renderer/SelectFieldListBoxRenderer.java

/form/renderer/TextAreaRenderer.java

/form/FormProperty.java (some properties were moved from Html2PdfProperty)

Changed radio buttons creation logic to make them pure widgets instead of form fields: radio buttons changed from a PdfFormField to a PdfFormAnnotation and should be explicitly added to the desired radio button group.

For radio buttons use PdfFormAnnotation instead of PdfFormField and explicitly add it to the group by using PdfButtonFormField.addKid

Example of usage:

JAVA
PdfButtonFormField group = new RadioFormFieldBuilder(doc, formFieldName)
                 .createRadioGroup();
PdfFormAnnotation radio = builder.createRadioButton("1", rect)
                .setVisibility(PdfFormAnnotation.VISIBLE);
group.addKid(radio);

More user friendly enums are introduced/used for check box types and fields justification.

  • PdfFormField flags related to check box creation: com.itextpdf.forms.fields.properties.CheckBoxType is added,

    • public PdfFormField setCheckType(int checkType) changed to public PdfFormField setCheckType(CheckBoxType checkType)

  • TextAlignment is used for justification:

    • PdfFormField#setJustification(int) is changed to PdfFormField#setJustification(com.itextpdf.layout.properties.TextAlignment),

    • public Integer getJustification() is changed to public TextAlignment getJustification()

Use CheckBoxType enum values instead of integer values while setting check type. Also use TextAlignment for setting/getting justification.

Moved radio button, push button, checkbox, text field drawing logic from forms to renderers (drawButton, drawCheckBox, drawPdfACheckBox, drawRadioBorder and drawRadioField are deleted since those methods aren't needed anymore).

  • drawRadioAppearance is replaced by drawRadioButtonAndSaveAppearance

  • drawTextAppearance, drawMultiLineTextAppearance are replaced by drawTextFormFieldAndSaveAppearance

  • drawPushButtonAppearance is replaced by drawPushButtonFieldAndSaveAppearance

  • drawCheckAppearance, drawPdfA2CheckAppearance are replaced by drawCheckBoxAndSaveAppearance

  • drawChoiceAppearance moved

InputButton was merged with Button, also InputButtonRenderer was merged with ButtonRenderer which extends AbstractTextFieldRenderer instead of BlockRenderer. We can create one-line push button by using public Button setSingleLineValue(String value) to set caption for Button element.
Also FormProperty.FORM_FIELD_VALUE is not supported for Button element.
Font color issue is fixed: color set to an annotation with setColor method is now applied to button fields.
Appearance of buttons with multiple elements inside changed to be similar to how it is displayed when opening the HTML document: all children are centered and wrap to a new line if necessary.
After adding a field inside a button this field will be flattened.

Use Button instead of InputButton and setSingleLineValue method instead of setting FormProperty.FORM_FIELD_VALUE. For multiline value use setValue or create paragraph and use add(IBlockElement)

Drawing logic related to comb property and choice fields was moved to the new TextAndChoiceLegacyDrawer class.


exceptions/FormsExceptionMessageConstant.java

  • WRONG_FORM_FIELD_ADD_ANNOTATION_TO_THE_FIELD is deleted,

  • N_ENTRY_IS_REQUIRED_FOR_APPEARANCE_DICTIONARY is moved to FormsLogMessageConstants




JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.