Skip to content
Document Authoring DA  API Docs v2.1.0
npmGitHub

FieldNEW

Field:

A field in the document: what it computes, and the text that shows it.

A field object’s properties are read-only: assigning to them changes nothing in the document. Change a field through its methods: its text with Field.setText, its definition with Field.setDefinition, the text it covers with Field.setExtent.

A field’s text is ordinary document text, so it can also be formatted and edited through a TextView. Editing text strictly inside a field keeps it part of the field; writing over all of a field’s text removes the field, and text written at its start or end is outside it. Updating the field (Field.update, DocAuthDocument.updateFields, or “Update field” in the editor) overwrites its text, including text edited by hand, with the computed value.

A field object is a snapshot, valid only inside the transaction that returned it. Its methods return the field as it is after the change, while the object they were called on keeps the values it was read with; any other edit of the document can make its anchor stale. Keep its id to find the same field again.

Read the text every field shows:

for (const field of draft.fields().all()) {
console.log(field.definition.type, field.value);
}

readonly id: string

Identifier of the field, stable across transactions.


readonly definition: FieldDefinition

What the field computes.


readonly anchor: object

Where the field’s text is, in document order. A field that spans several paragraphs, such as a table of contents, has one range per paragraph.

type: "text"

ranges: TextAnchorRange[]


readonly parentId: string | null

The id of the field this one is nested in, or null when it is not nested.


readonly value: string

The text the field shows, with a line break between paragraphs.

A shortcut for joining the text of the Field.anchor ranges, except when the field has no value: then it is '', while the anchor’s text holds a placeholder (a space. '' does not tell a field with no value apart from one whose value is empty. A field has no value until the document is next laid out or its fields are updated, after it is added or its definition changes. A field whose value is computed per page (Field.computedPerPage) always returns ''.


readonly computedPerPage: boolean

Whether the value is computed for every page it is drawn on, as for a page number or page count in a header or footer. Such a field stores no value, so its value is always ''.

setDefinition(definition): Field | undefined

Replaces the field’s definition: its options, or its type when the new type has a value of the same shape (a page number can become a page count, but not a table of contents). The field keeps its place, and its value is cleared until the document is next laid out or its fields are updated.

FieldDefinitionInput

Field | undefined

The field as it is after the change. This object keeps the values it was read with. Returns undefined, changing nothing, when the field no longer exists, the definition is invalid or of another shape, the participant may not edit the document, or the transaction is a review transaction: a definition change cannot be tracked.

Unlinking the field and adding a new one on its text gives a field with the new definition too, but with a new id; this keeps the field’s id.

Point a page reference at another bookmark, and make it a link:

const reference = draft.fields().all().find((field) => field.definition.type === 'pageReference');
reference?.setDefinition({ type: 'pageReference', bookmark: 'Results', hyperlink: true });

Turn every page number into a page count:

for (const field of draft.fields().all()) {
if (field.definition.type === 'pageNumber') {
field.setDefinition({ type: 'pageCount' });
}
}

setText(text): Field | undefined

Replaces the field’s whole value with text and keeps it a field, as one run with the formatting of the value’s first run. For a table of contents, each line of text becomes one paragraph.

In a review transaction the old value is marked deleted and text is inserted as a tracked insertion inside the field.

string

Field | undefined

The field as it is after the change. This object keeps the values it was read with. Returns undefined, changing nothing, when the field no longer exists, its value is computed per page (Field.computedPerPage), the participant may not edit the document, or a table of contents is changed in a review transaction.

Writing text over the whole value through a TextView removes the field instead. This method is a shortcut for writing text next to the value, extending the field over it with Field.setExtent, and deleting the old text. In a review transaction, where setExtent is not available, it is the only way to change an inline field’s text.

Updating the field later, in the editor or through the API, overwrites this text with the computed value.

Show a known page number without waiting for the document to be laid out:

const reference = draft.fields().all().find((field) => field.definition.type === 'pageReference');
reference?.setText('12');

setExtent(span): Field | undefined

Moves the field’s boundaries to span: to extend a field, write the new text with the text API, then call this with a span reaching it. Text left outside the span stays in the document as ordinary text.

TextSpan

Field | undefined

The field as it is after the change. This object keeps the values it was read with. Returns undefined, changing nothing, for a span FieldCollection.add would refuse, a span that leaves out a field nested in this one, a field that no longer exists, a participant who may not edit the document, or a review transaction: moving a field’s boundaries cannot be tracked.

Unlinking the field and adding a new one over span covers the same text too, but gives a field with a new id; this keeps the field’s id.

Write ” (top)” after a page reference and make it part of the field:

const reference = draft.fields().all().find((field) => field.definition.type === 'pageReference');
const value = reference?.anchor.ranges[0];
if (reference && value) {
const textView = value.paragraph.asTextView();
const added = textView.addInlineText(' (top)', { placement: 'after', range: value.range });
reference.setExtent({ from: { textView, range: value.range }, to: { textView, range: added } });
}

unlink(): boolean

Turns the field back into ordinary text: its text stays exactly as it is and no longer belongs to the field. Fields nested in a table of contents, such as the page numbers of its entries, are unlinked with it; fields nested in any other field stay.

boolean

true when the field was unlinked. Returns false, changing nothing, when the field no longer exists, the participant may not edit the document, or the transaction is a review transaction: unlinking a field cannot be tracked.

Nothing else keeps a field’s text while dropping the field: writing over the text replaces it, and Field.remove deletes it.

Freeze every text reference as plain text, so updates no longer change it:

for (const field of draft.fields().all()) {
if (field.definition.type === 'textReference') {
field.unlink();
}
}

remove(): boolean

Deletes the field and its text. A table of contents’ paragraphs are deleted whole, except one that ends a section, which is emptied so the section stays; text sharing a paragraph with an inline field stays, and a field spanning several paragraphs leaves the text before and after it joined in one paragraph.

In a review transaction the field’s text is marked deleted instead, and the field goes once the deletion is accepted.

boolean

true when the field was removed. Returns false, changing nothing, when the field no longer exists or the participant may not edit the document.

This is a shortcut for deleting all of the field’s text through a TextView, which removes the field too; it also deletes a table of contents’ paragraphs in one call.

Remove the table of contents:

const toc = draft.fields().all().find((field) => field.definition.type === 'tableOfContents');
toc?.remove();

update(options?): boolean

Asks for the field’s value to be recomputed once the transaction is committed, as the editor’s “Update field” does. The transaction’s promise then resolves only after the document is laid out and the value is written, and in the editor one undo reverts the transaction and the update together.

FieldUpdateOptions

boolean

true when the update was requested, or when the field needs none because its value is computed per page (Field.computedPerPage). Returns false, requesting nothing, when the field no longer exists or the participant is not an owner: an update is not tracked, so a reviewer or a reader may not run it.

The update overwrites the field’s text, including text edited by hand. A transaction that is not committed updates nothing. The update runs after the commit, so if it fails, the transaction’s promise rejects while the transaction’s own changes stay committed. In a collaborative document an update needs a connection: offline, the transaction rejects with a NotPermittedError and none of its changes commit. Only this method recomputes chosen fields; to update every field of the document, use DocAuthDocument.updateFields.

Refresh a table of contents’ page numbers once the transaction is committed, keeping its entries’ text:

await doc.transaction(async ({ draft }) => {
const toc = draft.fields().all().find((field) => field.definition.type === 'tableOfContents');
toc?.update({ pageNumbersOnly: true });
return true;
});
// The table of contents is up to date here.