Skip to content

PDF Form Properties ​

This chapter describes in detail how to use Foxit PDF SDK for Web to work with PDF form properties, including dynamically updating properties, listening for property changes, and developing custom property editor components based on the form-designer extension. Before reading this chapter, it is recommended that you first understand the following:

  1. Core concepts:
  2. Fundamentals of UI customization:

Form Widget Properties ​

PDF form widget properties mainly fall into two categories: visual properties such as rotation angle and color scheme, and behavioral properties such as editable state and validation rules. This section explains in depth the property APIs provided by Foxit PDF SDK for Web and their real-time change-listening mechanisms.

Get Form Widgets ​

Foxit PDF SDK for Web provides two modes for obtaining form widget instances.

Active Retrieval Mode ​

  1. Coordinate lookup via PDFForm.getWidgetAtPoint:
    • Input: page index, coordinate point, and an optional form field type filter
    • Output: a form widget instance that matches the specified location and type
  2. Object identifier lookup via PDFPage.getAnnotsByObjectNumArray:
    • Input: a predefined objectNumber array
    • Output: a collection of PDF annotation objects, which still requires a second type filter
  3. Full traversal via PDFPage.getAnnots:
    • Output: all annotation objects on the current page, which should be filtered by Annot_Type.widget
  4. Field-associated lookup via PDFFormField.getWidget:
    • Prerequisite: use getWidgetsCount to get the valid index range
    • Output: the widget collection associated with a specified form field
javascript
// Coordinate lookup example
const widget = await form.getWidgetAtPoint(0, {x: 100, y: 100});
const pushButtonWidget = await form.getWidgetAtPoint(0, {x: 100, y: 100}, PDF.form.FieldType.PushButton);

// Object identifier lookup example
const [widget] = await page.getAnnotsByObjNumArray([12345]);

// Iterate through all annotations on the page and filter form widgets by type
const annots = await page.getAnnots();
const filteredWidgets = annots.filter(it => {
    return it.getType() === PDF.annots.constant.Annot_Type.widget;
});

// Field-associated lookup example
const field = await form.getField("Field name");
const widgetCount = await field.getWidgetsCount();
const widgets = await Promise.all(
    Array.from({length: widgetCount}, (_, i) => {
        return field.getWidget(i);
    })
);

Event-Driven Mode ​

By registering data event listeners, you can retrieve widgets dynamically:

  • DataEvents.annotationAdded: triggered when an annotation or form widget is added; form widgets must be filtered by type.
  • DataEvents.annotationUpdated: triggered when annotation or form widget properties change; filtering by type is also required.
  • DataEvents.annotationRemoved: triggered when an annotation or form widget is removed. Removed objects only retain getObjectNumber and getAnnotId.

Get and Set Form Widget Properties ​

You can modify and retrieve properties directly through the Widget interface. The following example shows the basic usage:

javascript
// Get all annotations
const annots = await page.getAnnots();
// Filter form widgets
const widgets = annots.filter(it => {
    return it.getType() === PDF.annots.constant.Annot_Type.widget;
});

// Rotate all form widgets by 90 degrees
await Promise.all(
    widgets.map(widget => {
        return widget.setRotation(PDF.form.FormWidgetRotation.ROTATION_90)
    })
);
// Get the rotation angle of the first form widget
const rotation = await widgets[0].getRotation();

Listen for Form Widget Property Changes ​

You can monitor property changes of form widgets by listening to the DataEvents.annotationUpdated event.

javascript
pdfui.addPDFViewerEventListener(DataEvents.annotationUpdated, (annots, page, updateType) => {

})

Parameters of the event callback:

  • annots: an array of annotations or form widgets whose properties have changed; filter form widgets by type.
  • page: the page object that contains the annotations or form widgets whose properties have changed.
  • updateType: the type of update, which can be one of the values in PDF.constant.AnnotUpdatedType.

You can use updateType to determine which property has changed. For details, see AnnotUpdatedType.

Form Field Properties ​

Get Form Fields ​

You can obtain a form field instance in the following ways:

Example:

javascript
// Get a form field by field name
const field = await form.getField("Field name");
// Get a form field by page index and point coordinates
const field = await form.getFieldAtPosition(0, {x: 100, y: 100});
// Get a form field through the form widget
const field = widget.getField();

Get and Set Form Field Properties ​

For retrieving and setting form field properties, refer to the PDFFormField API documentation. Example:

javascript
const field = await form.getField("Field name");
// Get the form field value
const value = await field.getValue();
// Update the form field value
await field.setValue(value);

Listen for Form Field Property Changes ​

The form field property change event is triggered when a form field property changes. You can listen to DataEvents.formFieldPropertyUpdated to capture these updates.

javascript
pdfui.addPDFViewerEventListener(DataEvents.formFieldPropertyUpdated, (doc, fieldName, propertyName) => {

})

In the callback for the form field property change event, you can access the following three parameters:

  • doc: the document object that owns the form field whose property has changed
  • fieldName: the name of the form field whose property has changed
  • propertyName: the name of the changed property. See PDF.form.FormFieldPropertyName.

Custom Property Editor Components ​

The form-designer Addon provides powerful features and components for form design. Starting from version 11.0.0, this add-on supports custom property editor components, further improving the flexibility and extensibility of form design.

Using PDFFormProperty ​

PDFFormProperty is a utility class provided by the form-designer Addon specifically for supporting custom property editor components. It offers the following capabilities:

  • It can merge property values from multiple selected form fields. If the property values differ and cannot be merged, the property value is automatically cleared and the state is marked unavailable.
  • It can determine whether the corresponding property editor component should be displayed based on the selected form field types.
  • It can determine whether the corresponding property editor component should be enabled or disabled based on the selected form field types and property values.

The form-designer Addon has already constructed a set of PDFFormProperty instances for supported form properties, and developers can obtain them directly through PDFFormPropertiesService.

javascript

const formDesigner = await pdfui.getAddonInstance('FormDesigner')
const propertiesService = formDesigner.getPDFFormPropertiesService();

const fieldNameProperty = propertiesService.getFieldName();

fieldNameProperty.onChange(() => {
    const {
        // Indicates whether the property has a value. It is false when no form field is selected, or when multiple fields are selected and their values cannot be merged; otherwise it is true.
        hasValue,
        // Property value
        value,
        // Indicates whether the property is available. It is false when the selected form fields do not support the property, or when their properties cannot be edited together; otherwise it is true.
        available,
        // Indicates whether the property editor component is visible. It is false when the selected form fields do not support the property, or when their properties cannot be edited together; otherwise it is true.
        visible
    } = fieldNameProperty;
})

const exportValueProperty = propertiesService.getExportValueProperty()

The following are several typical scenarios that explain the state of PDFFormProperty:

  1. The user selects only one PushButton form field. For fieldNameProperty, the state values are:

    • hasValue: true
    • value: 'PushButton 0'
    • available: true
    • visible: true In this case, the fieldName property editor displays 'PushButton 0', and the component is visible and editable.
  2. The user selects one PushButton field and one ListBox field. For fieldNameProperty, the state values are:

    • hasValue: false
    • value: undefined
    • available: false
    • visible: true In this case, the fieldName property editor appears blank, and the component is visible but not editable because the two fields cannot be assigned the same name at the same time.
  3. The user selects one PushButton field. For exportValueProperty, the state values are:

    • hasValue: false
    • value: undefined
    • available: false
    • visible: false In this case, the ExportValue property editor is hidden and unavailable because PushButton does not support this property.

PDFFormProperty.onChange method:

This method listens for property changes. The change callback is triggered when the user selects form fields or when form field property values change. The following example uses a React component:

  1. First, create hooks to obtain a PDFFormProperty instance:

    jsx
    function useFormDesignerAddonInstance() {
        const context = useContext(PDFUIContext); // PDFUIContext, used to share the PDFUI object
        const pdfui = context.current;
        const [instance, setInstance] = useState();
        if (pdfui && instance) {
            pdfui.getAddonInstance('FormDesigner').then(instance => {
                setInstance(instance);
            });
        }
        return instance;
    }
    function useFormPropertiesService() {
        const formDesigner = useFormDesignerAddonInstance();
        return formDesigner?.getPDFFormPropertiesService();
    }
    function usePDFFormProperty(pdfFormPropertyFactory) {
        const formPropertiesService = useFormPropertiesService();
        const [property, setProperty] = useState();
        useEffect(() => {
            if(property) {
                return;
            }
            if(!formPropertiesService) {
                return;
            }
            const property = pdfFormPropertyFactory(formPropertiesService);
            setProperty(property);
        }, [property, formPropertiesService])
    
        useEffect(() => {
            if(!property) {
                return;
            }
            return property.onChange(() => {
                setProperty(property);
            });
        }, [property])
        return property;
    }
  2. Use it in a React component:

    jsx
    function FieldNameEditor() {
        const formPropertiesService = useFormPropertiesService();
        const fieldNameProperty = usePDFFormProperty(pdfFormPropertyService => {
            return pdfFormPropertyService.getFieldName();
        })
        const [value, setValue] = useState()
        // Because fieldNameProperty.value is read-only, binding it directly to <input> prevents user edits. Create a new state instead.
        useEffect(() => {
            if(!fieldNameProperty?.hasValue) {
                setValue('');
            } else {
                setValue(fieldNameProperty.value)
            }
        }, [fieldNameProperty?.hasValue, fieldNameProperty?.value])
        return <input
            readonly={!fieldNameProperty?.available}
            className={fieldNameProperty?.visible ? '' : 'hide'}
            value={value}
            onChange={(event) => {
                const newFieldName = event.target.value;
                setValue(newFieldName);
                const fields = formPropertiesService.getSelectedFields();
                // When the user modifies the content, apply the updated data to the form fields
                fields.forEach(field => {
                    field.setName(newFieldName);
                });
            }}
        ></input>
    }

Note: The examples above are for demonstration only. In actual development, adjust and implement them according to your specific scenario.

Built-In Form Property Editor Components ​

For built-in form property editor components, refer to Built-In Form Property Editor Components.

Custom Form Properties Dialog ​

For a custom form properties dialog, refer to Customize Form Properties Dialog.