Read the Terminology for the concepts used in this guide.
This guide demonstrates the bundled survey form definition.
You will load the form model, inspect its contents, and see how invalid definitions are reported.
Find these files with
system.file("examples", "survey", package = "form.model").
The populated form contains three synthetic observations. The empty form has no data rows.
library(form.model)
# Load the bundled survey form model.
model_definition <- read_form_model("examples/survey/form.yaml", "form.model")
# Display its identity and worksheet summary.
model_definition
#> <form_model> survey @ 2026.2 (schema 1.0.0)
#> 34 fields; 6 sheetsThe example ships under inst/examples/survey/, so it
remains available after installation.
The example reads form.yaml from that directory.
Choose the version directory explicitly; the loader never searches for a latest version.
read_form_model(path, package) remains available when
you need to load an explicit filename.
To require an exact form identity and version:
A form_model is the checked definition itself, with an
S3 class:
# Inspect the top-level form model properties.
names(model_definition)
#> [1] "schema_version" "form" "references" "sheets"It directly contains the form identity, versions, reference declarations, and sheets.
Sheets use worksheet names, and their fields use local field names:
# List the worksheets in declaration order.
names(model_definition$sheets)
#> [1] "Metadata" "Observations" "Samples" "Measurements" "Equipment"
#> [6] "Notes"
# List the metadata fields in declaration order.
names(model_definition$sheets$Metadata$fields)
#> [1] "submission" "date" "contact_email" "comment"
# Inspect the submission identifier's requiredness, cell and type.
model_definition$sheets$Metadata$fields$submission[c("mandatory", "location", "type")]
#> $mandatory
#> [1] TRUE
#>
#> $location
#> [1] "C2"
#>
#> $type
#> [1] "string"The YAML path is used in loading errors, then discarded after a successful load.
The S3 class selects the compact print() method shown
above. It does not make the object immutable.
# Inspect the observation unit's allowed values and required-field condition.
form_field(model_definition, "Observations.unit")[c("enum", "required_field")]
#> $enum
#> $enum[[1]]
#> [1] "cm"
#>
#> $enum[[2]]
#> [1] "m"
#>
#>
#> $required_field
#> [1] "length"
# Inspect the station's reference binding.
form_field(model_definition, "Observations.station")$reference
#> $catalogue
#> [1] "code_lists"
#>
#> $table
#> [1] "stations"
#>
#> $lookup
#> [1] "code"
#>
#> $severity
#> [1] "error"
# Locate the first observation row in the form.
form_layout(model_definition, "Observations")$start_row
#> [1] 6
# Check the structure and consistency of the definition.
check_form_model(form_definition(model_definition))
#> <form_model_check> valid# Copy the definition for an invalid-reference example.
invalid_definition <- form_definition(model_definition)
# Point the station binding at an undeclared table.
invalid_definition$sheets$Observations$fields$station$reference$table <- "missing"
# Check the changed definition without throwing an error.
definition_check <- check_form_model(invalid_definition, resource = "my-definition.yaml")
# Display the reported form model errors.
definition_check$diagnostics
#> resource path
#> 1 my-definition.yaml $.sheets.Observations.fields.station.reference.table
#> message
#> 1 unknown reference table: missing
# Confirm that the changed definition was rejected.
stopifnot(!definition_check$valid)as_form_model() and read_form_model() throw
model_form_error when a definition is invalid.
# Capture the error raised when constructing the invalid form model.
definition_error <- tryCatch(
as_form_model(invalid_definition, "my-definition.yaml"), model_form_error = identity)
# Inspect the property that caused the error.
definition_error$path
#> [1] "$.sheets.Observations.fields.station.reference.table"
# Inspect the full set of definition errors.
definition_error$diagnostics
#> resource path
#> 1 my-definition.yaml $.sheets.Observations.fields.station.reference.table
#> message
#> 1 unknown reference table: missinghelp(package = "form.model").