Skip to contents

Build Test Coverage Coverage Website Latest release License

Neutral, versioned form definitions with explicit YAML resources and ordered workbook layouts.

Model checks validate definitions. They do not validate submitted form data.

Installation

Install the latest released version directly from GitHub:

install.packages("pak") # Once
pak::pak("ultreia-io/form.model@*release")

pak downloads the package and installs its dependencies automatically.

For the development version:

pak::pak("ultreia-io/form.model@develop")

Start here

library(form.model)
directory <- system.file("examples", package = "form.model")
m <- load_form_model("survey", directory)

form_field(m, "Observations.unit")[c("enum", "required_field")]
form_layout(m, "Observations")$start_row
check_form_model(form_definition(m))

The name survey resolves exactly to survey-form.yaml in the supplied directory.

Use separate directories for different versions. No directory scanning or latest-version selection occurs.

Explicit file loading and exact version selection remain available:

select_form_model(
  "examples/survey-form.yaml", "survey", "2026.2",
  package = "form.model"
)

Example workbooks

The installed examples/ directory includes survey.xlsx and survey-empty.xlsx, matching survey-form.yaml. The populated workbook contains three synthetic observations; the matching template has empty data regions. See inst/examples/README.md for the records and expected split.

Contract

  • Independent schema and form versions.
  • Ordered sheets, fields, fixed cells, and table columns.
  • Explicit types and compact constraints, including mandatory.
  • Separate code-list and registry declarations; callers supply their data.
  • Structured definition diagnostics and ordinary list/S3 values.
  • One runtime dependency: yaml. Loading the package has no external side effects.

Model defaults and conventions

These omitted properties receive values from form.model:

Model YAML Effective meaning
mandatory omitted The field may be absent or null; form_fields() returns mandatory = FALSE.
severity omitted An unmatched code or registry value is an error.

Table column counts are derived from the fields. Other omissions do not invent values.

Every sheet listed under sheets is mandatory. There is no sheet-level flag. Cell layouts declare column_count. Table column counts are derived from the fields, whose mapping order defines column order. An explicit table column_count is optional and must match the number of fields. An optional row_count declares an exact extent. Fixed fields must lie inside all declared dimensions.

form_definition() preserves the compact YAML declaration. form_sheets() and form_layout() expose the derived table column counts. form_fields() returns effective fields with derived full IDs, columns, and the resolved defaults above.

Declare code-list IDs under references.code_lists and registry IDs under references.registries. Use code_list or registry on a field to bind it to a declared ID. Registry bindings may specify matching: name, aliases, and severity. Each registry binding selects a column from its declared table. Inspect the declarations with form_code_lists() and form_registries().

Boundaries

This package loads, checks, and exposes form definitions.

Workbook reading, submitted-data validation, and database loading belong to consuming packages.

License

LGPL-2.1. See LICENSE.