AcroForm field access for documents and editors.
fields/1, field/2 and value/2 read from either source — a read-only
PdfElixide.Document or a mutable PdfElixide.Editor (source/0) — so
inspecting a form needs no editor. Writing needs one: put_value/3,
put_values/2 and update_value/3 take an Editor only, and each returns
it, so filling and saving compose as a pipeline.
"form.pdf"
|> PdfElixide.Editor.open!()
|> PdfElixide.Form.put_value!("full_name", "Jane Doe")
|> PdfElixide.Editor.save!("filled.pdf")
|> PdfElixide.Editor.close()Fields come back as one struct per field type, listed in
PdfElixide.Form.Field, each carrying the widget it is as a :kind and its
decoded /Ff bits as :flags, and are addressed by the fully qualified name
each carries. Only an existing field can be set — there is no way to add one — and
a name that is not in the form is
{:error, %PdfElixide.Error{reason: :not_found}}, from field/2 and
value/2 as much as from put_value/3. Signature fields are not fillable and
are not reported at all, and writing a check box or radio group back is not
always faithful.
A form whose field hierarchy is cyclic, or nested far deeper than any real
form, is reported as an error by every function here rather than read — a
cycle as :invalid_pdf, a hierarchy past the depth or size limit as
:unsupported.
Which lock a call takes follows its source: a shared read on a
PdfElixide.Document, and the editor's exclusive lock on a
PdfElixide.Editor — which fields/1 takes too, so concurrent form work on
one editor serializes even when it only reads. See the
Concurrency guide.
The Forms guide covers the field structs, both filling shapes, saving, and the signature and check-box caveats in full.
Summary
Functions
Returns the single form field carrying the given name.
Same as field/2 but raises an error if it fails.
Extracts form fields from the given PDF document or editor.
Extracts form fields from the given PDF document or editor, raising an error if it fails.
Writes the value of an existing form field on the given editor, and returns the editor it was given.
Writes the value of an existing form field on the given editor, raising an error if it fails.
Writes several form field values on the given editor, and returns the editor.
Writes several form field values on the given editor, raising an error if it fails.
Reads a form field's value, applies fun to it, writes the result back, and
returns the editor.
Reads a form field's value, applies fun to it and writes the result back,
raising an error if it fails.
Returns the value of the single form field carrying the given name.
Same as value/2 but raises an error if it fails.
Types
@type source() :: PdfElixide.Document.t() | PdfElixide.Editor.t()
Functions
@spec field(source(), String.t()) :: {:ok, PdfElixide.Form.Field.t()} | {:error, PdfElixide.Error.t()}
Returns the single form field carrying the given name.
The name is the fully qualified one PdfElixide.Form.Field describes. A name
that is not in the form is {:error, %PdfElixide.Error{reason: :not_found}};
a form with two fields of the same name answers with the first.
PdfElixide.Form.field(doc, "full_name")
#=> {:ok, %PdfElixide.Form.Field.Text{name: "full_name", kind: :single_line,
# value: "John Doe", flags: %PdfElixide.Form.Field.Text.Flags{…}}}
@spec field!(source(), String.t()) :: PdfElixide.Form.Field.t()
Same as field/2 but raises an error if it fails.
@spec fields(source()) :: {:ok, [PdfElixide.Form.Field.t()]} | {:error, PdfElixide.Error.t()}
Extracts form fields from the given PDF document or editor.
A document with no AcroForm answers {:ok, []}, as does one whose form
declares no fields.
Signature fields are not reported; this API covers fillable form fields only. See the Forms guide.
@spec fields!(source()) :: [PdfElixide.Form.Field.t()]
Extracts form fields from the given PDF document or editor, raising an error if it fails.
@spec put_value(PdfElixide.Editor.t(), String.t(), PdfElixide.Form.Field.value()) :: {:ok, PdfElixide.Editor.t()} | {:error, PdfElixide.Error.t()}
Writes the value of an existing form field on the given editor, and returns the editor it was given.
The value is a plain term, the same shape fields/1 returns — a string,
true/false, a list of strings, or nil. Anything else raises
ArgumentError; see PdfElixide.Form.Field.value/0 for the full set.
{:ok, editor} = PdfElixide.Form.put_value(editor, "full_name", "Jane Doe")
{:ok, editor} = PdfElixide.Form.put_value(editor, "subscribe", true)Button fields are limited to /Yes and /Off, and a signature field cannot be
written at all — it answers :not_found. The Forms guide
has both.
@spec put_value!(PdfElixide.Editor.t(), String.t(), PdfElixide.Form.Field.value()) :: PdfElixide.Editor.t()
Writes the value of an existing form field on the given editor, raising an error if it fails.
@spec put_values( PdfElixide.Editor.t(), Enumerable.t({String.t(), PdfElixide.Form.Field.value()}) ) :: {:ok, PdfElixide.Editor.t()} | {:error, PdfElixide.Error.t()}
Writes several form field values on the given editor, and returns the editor.
Takes a map with string keys, or a list of {name, value} pairs.
Everything is validated before anything is written, against a single fields/1
read. A name the form does not carry — a signature field included — is
{:error, %PdfElixide.Error{reason: :not_found}}, and a duplicated name, a
name that is not a string, or a value outside
PdfElixide.Form.Field.value/0 raises ArgumentError naming the field.
This is not a transaction. What can still fail after validation is the
handle itself — :closed, :panic, :lock_poisoned — and that stops at the
first error, leaving earlier writes applied.
A list is applied in its own order; a map is applied in Enum order, which is
unspecified, so pass a list where the order matters. Empty input returns
{:ok, editor} and makes no native call, so it leaves
PdfElixide.Editor.modified?/1 alone and answers the same way for a closed
editor.
It is a convenience, not a batching optimization — see the Concurrency guide for what it locks.
@spec put_values!( PdfElixide.Editor.t(), Enumerable.t({String.t(), PdfElixide.Form.Field.value()}) ) :: PdfElixide.Editor.t()
Writes several form field values on the given editor, raising an error if it fails.
@spec update_value( PdfElixide.Editor.t(), String.t(), (PdfElixide.Form.Field.value() -> PdfElixide.Form.Field.value()) ) :: {:ok, PdfElixide.Editor.t()} | {:error, PdfElixide.Error.t()}
Reads a form field's value, applies fun to it, writes the result back, and
returns the editor.
A field carrying no value hands fun a nil. A name the form does not carry
is {:error, %PdfElixide.Error{reason: :not_found}} and fun is not called.
Whatever fun returns is written by put_value/3 and must be a
PdfElixide.Form.Field.value/0.
This is a read and then a write, not an atomic read-modify-write — another process holding the same editor can write in between; see the Concurrency guide.
@spec update_value!( PdfElixide.Editor.t(), String.t(), (PdfElixide.Form.Field.value() -> PdfElixide.Form.Field.value()) ) :: PdfElixide.Editor.t()
Reads a form field's value, applies fun to it and writes the result back,
raising an error if it fails.
@spec value(source(), String.t()) :: {:ok, PdfElixide.Form.Field.value()} | {:error, PdfElixide.Error.t()}
Returns the value of the single form field carrying the given name.
{:ok, nil} means the field exists but carries no value — distinct from
{:error, %PdfElixide.Error{reason: :not_found}}, which means no field
carries that name. Reach for field/2 when the field's type is needed too.
PdfElixide.Form.value(doc, "full_name")
#=> {:ok, "John Doe"}
@spec value!(source(), String.t()) :: PdfElixide.Form.Field.value()
Same as value/2 but raises an error if it fails.