Heratio Help Center article. Category: Cataloguing & Description.
Forms & Templates
The Forms module lets administrators build custom metadata-entry templates, assign them to repositories, collections, or description levels, and drive editing of records (information objects, authority records, repositories, accessions) through those templates. This guide covers the template builder, field types, assignments, template-driven editing, and the submission audit trail.
Overview
A form template is a reusable definition of which fields appear when a record is created or edited, how those fields are grouped (sections and tabs), and which database columns each field writes to. Templates let an institution tailor cataloguing to a standard (for example ISAD(G) or Dublin Core) or to a specialised collection (for example photographs).
The module has four moving parts:
- Templates (
ahg_form_template) - the named forms, each tied to a record type (information object, accession, authority record, repository, and so on). - Fields (
ahg_form_field) - the inputs on a template, with type, label, help text, ordering, and validation. - Field mappings (
ahg_form_field_mapping) - the link between a form field and the actual database table / column it reads from and writes to, including i18n (translated) targets and optional value transformations. - Assignments (
ahg_form_assignment) - rules that decide which template applies to which records, scoped by repository, description level, and/or collection, with a priority order.
Two more tables support runtime behaviour: drafts (ahg_form_draft) for autosave, and a submission log (ahg_form_submission_log) for the audit trail of every save made through a template.
Heratio ships a starter library of system templates: ISAD-G Minimal, ISAD-G Full (all 26 elements across 7 areas), Dublin Core Simple (15 core elements), Accession Standard, and Photo Collection Item.
Key features
- Visual form builder - add, edit, reorder, and delete fields on a template.
- Fourteen field types covering text, structured input, choices, files, and layout elements.
- Sections and tabs to group fields, with single, sectioned, or tabbed layouts.
- Field-to-column mapping so a single form can write to the record table and its translated i18n table in one save, including value transformations (uppercase, lowercase, trim, prefix, JSON array).
- Context-aware assignment - the right template is chosen automatically for a record based on its repository, description level, and parent collection, with a priority tie-breaker.
- Template-driven editing - edit an existing record through a chosen or auto-resolved template; all writes happen in a single database transaction.
- Autosave drafts - in-progress form data is saved per user, template, and record so work is not lost.
- JSON export - download any template (with its fields) as a JSON file for backup or transfer.
- Duplicate / clone templates as a starting point for a new form.
- Submission audit log - every template-driven save is recorded with the user, record, timestamp, and submitted values.
- Statistics - counts of templates (by type), fields, assignments, pending drafts, and submissions in the last 30 days.
Field types
The builder offers these field types:
| Type | Use |
|---|---|
text |
Single-line text input |
textarea |
Multi-line plain text |
richtext |
Rich text editor |
date |
Date picker |
daterange |
Date range (start / end) |
select |
Single-choice dropdown |
multiselect |
Multiple-choice select |
autocomplete |
Type-ahead lookup (for example actors, taxonomy terms, repositories) |
checkbox |
Single checkbox / boolean |
radio |
Radio button group |
file |
File upload |
hidden |
Hidden value |
heading |
Section heading (layout only) |
divider |
Visual divider (layout only) |
Each field can carry: an internal field name, a visible label (with translated labels), help text, a placeholder, a default value, validation rules, options (for select / multiselect / radio), an autocomplete source (for example taxonomy:subject, actor:creator, repository:all), a section and tab name, a sort order, a width (full / half / third / quarter), and the required / read-only / hidden / repeatable flags.
How to use
All forms screens are under the /forms prefix and require an authenticated administrator. A set of aliases under /admin/formTemplates points to the same screens for menu and report links.
Open the forms dashboard
Go to /forms (route forms.index). The dashboard lists existing templates and shows statistics: template counts by type, total fields, assignments, pending drafts, and submissions in the last 30 days.
Browse templates
Go to /forms/browse (route forms.browse). Filter by record type or search by name / description. Each template shows its field count.
Create a template
Go to /forms/template/create (route forms.template.create).
- Enter a name, an optional description, and the record type (information object, authority record, repository, accession, deaccession, or rights).
- Choose a layout (single, sectioned, or tabbed).
- Submit. You are taken straight to the builder for the new template.
Build the form
Open /forms/builder/{id} (route forms.builder). In the builder you can:
- Add a field - choose a field type and label. The internal field name is derived from the label automatically. (AJAX route
forms.field.add.) - Edit a field - change the label, field name, help text, placeholder, default value, and the required / read-only flags. (AJAX route
forms.field.update.) - Delete a field - remove it from the template. (AJAX route
forms.field.delete.) - Reorder fields - drag fields into the order you want; the new sort order is saved. (AJAX route
forms.field.reorder.)
Preview a template
Open /forms/preview/{id} (route forms.preview) to see how the form renders to a user before assigning it.
Export a template
Download a template and all of its fields as a JSON file from /forms/template/{id}/export (route forms.template.export). The filename includes the template id and a timestamp.
Duplicate or delete a template
These are POST actions to /forms (route forms.post):
- Duplicate - clones the template (named "... (Copy)") and opens the builder on the copy.
- Delete - removes the template and all of its fields.
Browse the starter library
Go to /forms/library (route forms.library) to see the bundled starter templates (ISAD-G Minimal, ISAD-G Full, Dublin Core Simple, Accession Standard, Photo Collection Item) and their field counts.
Assignments: choosing which template applies
Assignments decide which template a record uses automatically.
Manage assignments
Go to /forms/assignments (route forms.assignments) to list current assignments with their template name and type, ordered by priority.
Create an assignment
Go to /forms/assignment/create (route forms.assignment.create).
Set:
- Template - the template to apply.
- Repository - scope to one repository (leave blank for all repositories).
- Level of description - scope to one description level (leave blank for all levels).
- Collection - scope to a specific collection / fonds.
- Priority - lower numbers win when several assignments match the same record.
- Inherit to children - apply the assignment to descendant records.
How a template is resolved
When a record is edited through the module, Heratio resolves the template like this:
- Assignments for the record's type are checked in priority order. An assignment matches only if every scope it sets (repository, level, collection) matches the record's context. For an information object, the context is built from the record's repository, description level, and the top-level collection found by walking up the parent chain. The first matching assignment wins.
- If no assignment matches, the global default template for that record type (the one flagged
is_defaultand active) is used. - If there is still no match, the module falls back to the standard edit page.
Template-driven editing
A record can be edited through a template using the edit dispatcher.
Edit a record with a template
Open /forms/edit/{entityType}/{entityId}/{templateId?} (route forms.template.edit). The entity type must be one of information_object, actor, repository, or accession. This route requires update permission (acl:update).
- If a template id is supplied, that template is used (its type must match the entity type).
- If no template id is supplied, the best-matching template is resolved automatically as described above.
- The form is pre-filled with the record's current values, read through the field mappings.
Save the record
Submitting posts to /forms/edit/{entityType}/{entityId}/submit/{templateId} (route forms.template.submit). On save:
- Each submitted field value is normalised by its type (numbers, checkboxes, dates, and trimmed text).
- For each field with one or more mappings, any configured transformation is applied (uppercase, lowercase, trim, prefix, JSON array).
- Writes are bucketed by target table; one update or insert is issued per table. Translated (i18n) targets are written to the correct culture row, inserting the row if it does not yet exist.
- All writes happen inside a single database transaction. If anything fails, the whole save is rolled back and the form is returned with the error and the entered values preserved.
- A row is written to the submission log recording the template, entity, the submitting user, the timestamp, and the submitted values.
- On success you are redirected back to the record (its public page for information objects).
Unmapped fields are ignored for writing but are still captured in the submission log.
Field mappings
A mapping (ahg_form_field_mapping) connects a form field to a real database location:
- Target table - for example
information_objectorinformation_object_i18n. - Target column - for example
titleorscope_and_content. - i18n flag and culture - whether the column lives in a translated table, and which culture (defaults to
en). - Transformation and config - an optional value transformation applied on save.
A single field may have several mappings (so one input can populate more than one column), and on read the first mapping that yields a value is used to pre-fill the field. The bundled ISAD-G Minimal template, for example, maps Title to information_object_i18n.title, Reference Code to information_object.identifier, Extent and Medium and Scope and Content to their i18n columns.
Drafts and autosave
While a form is being filled in, the data can be autosaved per user, template, and record through the autosave API (route forms.api.autosave, POST /api/forms/autosave). A draft is keyed by template, object type, object id, and user, so each user keeps their own in-progress copy. A companion lookup (route forms.api.template, GET /api/forms/template) resolves the appropriate template and its fields for a given object type and id, used by JavaScript widgets that render a form inline.
Configuration
The Forms module has no separate settings page; configuration is the templates, fields, mappings, and assignments themselves, all managed through the screens above.
Behaviour to keep in mind:
- System templates (
is_system = 1) are the bundled starter templates and are intended to be protected from deletion. - Default templates (
is_default = 1) act as the global fallback for their record type when no assignment matches. - Active flag (
is_active) - only active templates and assignments take part in resolution. - Validation, options, autocomplete sources, conditional logic, and translated labels are all stored per field and can be set when building the field. Choice fields store their options as a list of value / label pairs.
In line with Heratio's rules, all enumerated choices should come from the Dropdown Manager or the field's own options list rather than being hardcoded.
Troubleshooting
- "No form template configured for this entity" - no assignment matched the record and there is no active default template for its type. Create an assignment or mark a template as the default.
- "Template form_type does not match entity type" - the template you chose is for a different record type than the record you are editing; pick a template whose type matches.
- A saved value did not appear - confirm the field has a mapping to the correct table and column, and that the i18n flag and culture are set correctly for translated fields. Unmapped fields are logged but not written.
- Lost in-progress entry - autosave keeps a per-user draft; reopening the same record and template restores it.
References
- Source package:
packages/ahg-forms/ - Issue: GH #572