Skip to content

5. Forms & interactivity

Interactive form fields and document interactivity.

A PDF is not always a static page. It can carry links you can click, anchors you can jump to, and AcroForm fields a reader can fill in. This chapter covers the interactive features Rivoli PDF writes today, and is clear about where the edges are.

A hyperlink is an inline: it lives inside a paragraph and wraps link text. The convenience method is Paragraph.AddLink(target, text):

using Rivoli.Pdf;
using Rivoli.Pdf.Model;
var section = doc.AddSection();
section.Add(new Paragraph()
.Add("Read the ")
.AddLink("https://github.com/rivoli-ai/rivoli-pdf", "source on GitHub")
.Add(" for details."));

AddLink constructs a Hyperlink (namespace Rivoli.Pdf.Model) and appends it to the paragraph’s Inlines. The Target string decides the link kind:

Target formResult
https://…, mailto:…, any non-# stringExternal link: emitted as a URI action
#anchorInternal link: emitted as a named-destination jump

The renderer collects each hyperlink’s rendered rectangle and writes it as a /Link annotation on the page: external targets become a URI action, and #anchor targets become a /Dest referencing the anchor name (the part after the #).

Form fields are a document-level, cross-cutting collection rather than body content. The Document owns them through FormFields, and you add them with AddFormField:

using Rivoli.Pdf;
using Rivoli.Pdf.Forms;
var doc = Document.Create("Application Form");
doc.AddSection().AddHeading("Membership application");
doc.AddFormField(new TextField("full_name")
{
Rect = new Rectangle(72, 700, 320, 720), // left, bottom, right, top (points)
PageIndex = 0,
Tooltip = "Your full legal name",
Required = true,
});

Every field derives from the abstract FormField (namespace Rivoli.Pdf.Forms), which carries the properties common to all of them:

MemberPurpose
NameField name (must be unique within the document)
RectPlacement rectangle, in PDF points (Rectangle(left, bottom, right, top))
PageIndexZero-based page the widget appears on
ReadOnly, RequiredStandard AcroForm flags
TooltipHover / accessibility text
DefaultValueReset value

AddFormField enforces unique names and throws if you add two fields with the same Name. Companion methods round out management: GetFormField(name), RemoveFormField(field) / RemoveFormField(name), and ClearFormFields().

All seven AcroForm field types are present as authoring models:

TypeKey members
TextFieldValue, MaxLength, IsMultiLine, IsPassword, Alignment, FontSize
CheckBoxFieldIsChecked, ExportValue, Style
RadioButtonFieldGroupName, ExportValue, IsSelected, Style
ComboBoxFieldOptions, SelectedValue, IsEditable, SortOptions
ListBoxFieldOptions, SelectedValues, AllowMultipleSelection, VisibleItems
PushButtonFieldCaption, Action, SubmitUrl, JavaScript, Appearance
SignatureFieldSignReason, SignLocation, SignerName, IsSigned

A small interactive form:

// A required text field
doc.AddFormField(new TextField("email")
{
Rect = new Rectangle(72, 660, 320, 680),
PageIndex = 0,
IsMultiLine = false,
});
// A checkbox
doc.AddFormField(new CheckBoxField("subscribe", isChecked: true)
{
Rect = new Rectangle(72, 630, 90, 648),
PageIndex = 0,
ExportValue = "yes",
});
// A drop-down with options
var plan = new ComboBoxField("plan");
plan.Rect = new Rectangle(72, 600, 320, 618);
plan.PageIndex = 0;
plan.AddOption("Standard");
plan.AddOption("Premium", "PREM");
doc.AddFormField(plan);

Radio buttons share a group through their Name / GroupName: add one RadioButtonField per option, all with the same group name and distinct ExportValues.

When you save, the renderer writes the AcroForm dictionary, the field tree, and a widget annotation per field with a generated default appearance. Choice fields (ComboBoxField, ListBoxField) carry their Options through.

SignatureField defines the placeholder for a signature: its rectangle, reason, location, and signer metadata. Actually applying a cryptographic signature is a separate operation covered in the next chapter.