Getting started

Read the Terminology for the concepts used in this guide.

About 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.

Download the example files

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.

Load an installed example

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 sheets

The 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:

# Select the survey definition with the exact requested version.
select_form_model(
  "examples/survey/form.yaml", "survey", "2026.2",
  package = "form.model"
)
#> <form_model> survey @ 2026.2 (schema 1.0.0)
#> 34 fields; 6 sheets

What a form model contains

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 field constraints and locations

# 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

Diagnose a definition

# 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: missing