Create fillable PDF forms using JavaScript

Since version 2019.5, Nutrient Web SDK has included support for programmatically creating and removing form fields from a document, provided the license includes the Form Creator component (formerly Form Designer). As of version 2022.3, it’s also possible to create form fields using the built-in user interface.

A form field is a model representation of a visual form in a document. To create a form field, you have to first create the form element (also known as a widget annotation). For more information on the difference between a form field and a form element, refer to our introduction to forms guide.

Make sure to create a form field together with its associated widget annotation, since widget annotations that don’t have a matching form field can’t be created. Since the form field requires a widget annotation ID when created, you’ll need to generate a unique ID for your widget annotation via NutrientViewer#generateInstantId(). You can then add both the widget annotation and the form field to the document via NutrientViewer.Instance#create().

You can add any kind of form field to a document. For more information about the available form field types, check out the NutrientViewer.FormFields documentation.

If you need to allow widget annotations to be moved or resized through the UI, set the NutrientViewer.ViewState#formDesignMode property to true.

Adding a text form field

The following example consolidates both creating the widget annotation and a TextFormField:

// Create a new text form field.
const widget = new NutrientViewer.Annotations.WidgetAnnotation({
id: NutrientViewer.generateInstantId(),
pageIndex: 0,
formFieldName: "MyFormField",
boundingBox: new NutrientViewer.Geometry.Rect({
left: 100,
top: 75,
width: 200,
height: 80
})
});
const formField = new NutrientViewer.FormFields.TextFormField({
name: "MyFormField",
annotationIds: new NutrientViewer.Immutable.List([widget.id]),
value: "Text shown in the form field"
});
instance.create([widget, formField]);

It’s important to specify the formFieldName property on the widget annotation to link it to the name property of the corresponding form field that, in the case of the former example, is created together with the widget annotation. Likewise, the annotationIds property of the form field needs to be properly set with a NutrientViewer.Immutable.List of widget annotations linked to it.

Adding radio buttons and checkboxes

// Create two radio buttons and position them in the document.
// Note that both widget annotations have the same `formFieldName` value.
const radioWidget1 = new NutrientViewer.Annotations.WidgetAnnotation({
id: NutrientViewer.generateInstantId(),
pageIndex: 0,
formFieldName: "MyFormField",
boundingBox: new NutrientViewer.Geometry.Rect({
left: 100,
top: 100,
width: 20,
height: 20
})
});
const radioWidget2 = new NutrientViewer.Annotations.WidgetAnnotation({
id: NutrientViewer.generateInstantId(),
pageIndex: 0,
formFieldName: "MyFormField",
boundingBox: new NutrientViewer.Geometry.Rect({
left: 130,
top: 100,
width: 20,
height: 20
})
});
const formField = new NutrientViewer.FormFields.RadioButtonFormField({
name: "MyFormField",
annotationIds: new NutrientViewer.Immutable.List([
radioWidget1.id,
radioWidget2.id
]),
options: new NutrientViewer.Immutable.List([
new NutrientViewer.FormOption({
label: "Option 1",
value: "1"
}),
new NutrientViewer.FormOption({
label: "Option 2",
value: "2"
})
]),
defaultValue: "1"
});
instance.create([radioWidget1, radioWidget2, formField]);

Adding combo and list boxes

const widget = new NutrientViewer.Annotations.WidgetAnnotation({
id: NutrientViewer.generateInstantId(),
pageIndex: 0,
formFieldName: "MyFormField",
boundingBox: new NutrientViewer.Geometry.Rect({
left: 100,
top: 75,
width: 150,
height: 60
})
});
const formField = new NutrientViewer.FormFields.ComboBoxFormField({
name: "MyFormField",
annotationIds: new NutrientViewer.Immutable.List([widget.id]),
values: new NutrientViewer.Immutable.List(["orange"]), // initially selected value(s)
options: new NutrientViewer.Immutable.List([
// Available values.
new NutrientViewer.FormOption({ label: "Apple", value: "apple" }),
new NutrientViewer.FormOption({ label: "Banana", value: "banana" }),
new NutrientViewer.FormOption({ label: "Orange", value: "orange" })
])
});
instance.create([widget, formField]);

Updating form fields and widget annotations

To update a form field or widget annotation, you can use the NutrientViewer.Instance#update() method. You can also use it to change the widget annotations associated with the form field.

Removing form fields and widget annotations

You can easily remove any form field from a document using NutrientViewer.Instance#delete(). This call will also remove the associated widget annotations.

Editing widget annotations through the UI

The UI will allow each form field present on the current document page — regardless of if it was originally present on the document or if it was added using the programmatic API as outlined in this guide — to be fillable by users.

If you want to allow your users to adjust the placement of the form elements or resize them, you’ll have to activate the form design mode.

You can do this by setting the NutrientViewer.ViewState#formDesignMode property to true:

// During initialization.
NutrientViewer.load({
// Your configuration.
initialViewState: new NutrientViewer.ViewState({ formDesignMode: true })
});
// Or after an instance has been created.
instance.setViewState((viewState) =>
viewState.set("formDesignMode", true)
);