Structured Data Capture
2.8.0 - CI Build

Structured Data Capture, published by HL7 International - FHIR Infrastructure Work Group. This is not an authorized publication; it is the continuous build for version 2.8.0). This version is based on the current content of https://github.com/HL7/sdc/ and changes regularly. See the Directory of published versions

Advanced form behavior and calculation

Simple questionnaires only need simple behavior. All questions get displayed in order. The only 'behavior' defined in the questionnaire is whether a given question must be answered and whether multiple answers are permitted or not. However, for more sophisticated forms, there may be a need to set default answers, to enforce rules around the allowed answers (such as length, size, types of references), and/or to make the behavior of the questionnaire dynamic based on previous answers. The FHIR specification provides core elements that allow some of these things, and common extensions for others. This implementation guide supplements the core FHIR specification with additional extensions. It also defines the sdc-questionnaire-behave profile to highlight what extensions are available and where they are intended to be used. It also identifies specific 'must support' extensions that systems that claim to support SDC rendering SHALL be capable of authoring and/or rendering, as befits the CapabilityStatement(s) they claim conformance to.

Element and Overview

The following sub-sections describe the different core elements and extensions available to control the 'behavior' of a questionnaire. Each extension includes the following information:

  • Code: This is the name of the core element or the unique label for the extension. The extension label appears at the end of the URL of the 'source' (below). In this implementation guide, extensions are generally just referred to by their code.
  • Source: This will either be 'N/A', 'Core', 'Questionnaire' or 'SDC'. 'N/A' indicates that the element is part of the core spec, not an extension. 'Core' indicates that the extension is defined in the core specification and is not specific to the Questionnaire resource. The base URL for 'core' extensions is http://hl7.org/fhir/StructureDefinition/. Questionnaire indicates an extension defined in the core specification that is specific to Questionnaires. The base URL for 'Questionnaire' extensions is http://hl7.org/fhir/StructureDefinition/questionnaire-. SDC extensions are defined within this implementation guide. Their base URL is http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-
  • Location: This indicates where the element or extension can appear. Possible values are 'root' (for those that appear directly on the Questionnaire element), 'item' (for those that can appear on any type of item) or 'question' for those that can only appear on question items. In some cases, additional restrictions/guidance will be provided
  • Data Type: Indicates what content the element or extension can have.

Both core elements and extensions will have explanatory text that provides additional guidance on how the extension is used.

Value constraints

These elements all constrain the allowed values for answers to Questionnaires.

Code Source Location Data Type Example
maxLength Core question integer example

This core element is typically used with strings, but can theoretically be used for other variable-length simple types (e.g. to limit the maximum precision of a 'time' element). It SHALL NOT be used for complex types such as choice, open-choice, quantity, attachment or reference. It establishes the maximum length of the answer in characters. Be aware that in UTF-8, some characters may take multiple bytes, so maxLength does not place a specific constraint on the maximum number of bytes. If not specified, the maximum length is established by the data type. (For example, in FHIR the 'string' data type has a maximum character length of 1 megabyte (2^20).)

This element SHALL be greater than or equal to the value of minLength if both are specified. If set to a value greater than the inherent maximum length of the data type (e.g. 10 for date), the extension will be ignored.

minLength Core question integer example

This extension allows setting a minimum length for answers with a simple type. Like maxLength, it can only be used on simple types, not choice, open-choice, quantity, attachment or reference. It is typically used on strings to help ensure a minimum amount of detail is provided. However, it can also be used to set a minimum precision for variable-length types such as date or time. E.g. to enforce that a date includes at least the year and month, the minimum length could be set to 7.

This element SHALL NOT be greater than the value of maxLength if both are specified, or greater than the maximum permitted length for the FHIR simple type if not specified. (For example, the maximum length of date is 10, so a minLength of 11 on a question with an item.type of 'date' would be an error.)

regex Core question string example

This allows checking that an extension adheres to a regular expression. For example, enforcing the ANA NAN syntax of a Canadian postal code. The regular expression SHALL adhere to the same requirements as defined for the FHIRPath matches operation. Also see the entryFormat which might be a good way of displaying the desired format to the user. (For example, 'ANA NAN' which can be conveyed using 'entryFormat' is more intuitive for most users than seeing the actual regex (\d[A-Z]\d [A-Z]\d[A-Z]).

minValue Core date, dateTime, time, decimal, integer as per question type example

This extension is used for questions with simple quantitative types. The extension allows establishing the lower bound for an answer. For example, ensuring that birth dates are >= 1990-01-01 or an integer is greater than or equal to 0. (Note that the integer and decimal types both allow negative numbers if not constrained.) This extension can be used together with the cqf-calculatedValue extension to establish a dynamic limit. For example, ensuring that a date of birth will result in a maximum age by setting minValue with an expression of 'today() - 18 years'.

The minValue SHALL be less than or equal to the maxValue, if both are specified. If min and/or max are calculated values, care should be taken to ensure that they cannot ever conflict. I.e. It should never be possible for calculated max to be less than calculated min. If this does occur, systems SHALL prohibit a value from being specified for the element for so long as the conflict exists. If the question is required, this may mean that it is not possible to mark the QuestionnaireResponse as "completed".

maxValue Core date, dateTime, time, decimal, integer as per question type example

This extension is used for questions with simple quantitative types. The extension allows establishing the upper bound for an answer. For example, ensuring that birth dates are >= 1990-01-01 or an integer is greater than or equal to 0. (Note that the integer and decimal types both allow negative numbers if not constrained.) This extension can be used together with the cqf-calculatedValue extension to establish a dynamic limit. For example, ensuring that a date of birth will result in a minimum age by setting maxValue with an expression of 'today() - 18 years'.

The minValue SHALL be less than or equal to the maxValue, if both are specified. If min and/or max are calculated values, care should be taken to ensure that they cannot ever conflict. I.e. It should never be possible for calculated max to be less than calculated min. If this does occur, systems SHALL prohibit a value from being specified for the element for so long as the conflict exists. If the question is required, this may mean that it is not possible to mark the QuestionnaireResponse as "completed".

minQuantity SDC Quantity Quantity example

Same as minValue but for Quantity data types, it allows establishing the lower bound for an answer. Unlike straightforward comparisons with simple quantitative types, when performing the min and/or max checks for Quantity types, the answer.valueQuantity needs to be converted to the same units as the min/maxQuantity unit prior to comparison. This extension must only be used if the set of permitted units is constrained to UCUM codes.

The minQuantity SHALL be less than or equal to the maxQuantity, if both are specified. This extension can be used together with the cqf-calculatedValue extension to establish a dynamic limit. If min and/or max are calculated values, care should be taken to ensure that they cannot ever conflict. I.e. It should never be possible for calculated max to be less than calculated min. If this does occur, systems SHALL prohibit a value from being specified for the element for so long as the conflict exists. If the question is required, this may mean that it is not possible to mark the QuestionnaireResponse as "completed".

maxQuantity SDC Quantity Quantity example

Same as maxValue but for Quantity data types, it allows establishing the upper bound for an answer. Unlike straightforward comparisons with simple quantitative types, when performing the min and/or max checks for Quantity types, the answer.valueQuantity needs to be converted to the same units as the min/maxQuantity unit prior to comparison. This extension must only be used if the set of permitted units is constrained to UCUM codes.

The minQuantity SHALL be less than or equal to the maxQuantity, if both are specified. This extension can be used together with the cqf-calculatedValue extension to establish a dynamic limit. If min and/or max are calculated values, care should be taken to ensure that they cannot ever conflict. I.e. It should never be possible for calculated max to be less than calculated min. If this does occur, systems SHALL prohibit a value from being specified for the element for so long as the conflict exists. If the question is required, this may mean that it is not possible to mark the QuestionnaireResponse as "completed".

maxDecimalPlaces Core decimal integer example

For decimal types, this indicates the maximum precision below the decimal. For example, limiting a dollar amount to 2 decimal places.

mimeType Core attachment code example

When capturing attachments, this allows constraining the mime type of the attached data. Multiple repetitions can be specified to allow more than one candidate type. For example, if the attachment is intended to be an image, repetitions of this extension could constrain attachments to be image/jpeg, image/png or image/bmp.

maxSize Core Attachment decimal example

This extension is also used for questions with type of 'attachment'. It allows specifying an upper bound on the size of the attachment in bytes. This can help ensure that data embedded in the QuestionnaireResponse is 'manageable' and that a user does not accidentally attach a photo, document or something else that's unreasonably large (10s of megabytes or more).

Choice Restriction

These elements constrain what choices are available as well as how many answers can be/must be specified.

Code Source Location Data Type Example
answerOption Core question integer, date, time, string, Coding, Reference example

This allows constraining the allowed value for a question item's answer to an enumerated set. Each answerOption repetition indicates one of the possible allowed values. The answer to the question, if answered, SHALL match one of the specified repetitions unless the item.type is open-choice. The type of the answerOption must match the type of the question. (Coding is used for both choice and open-choice.)

There are three mechanisms to enumerate the permitted answers for a question: this element, the answerValueSet element, and the answerExpression extension. answerValueSet only supports defining values for 'string' and Coding elements. (For 'string', the allowed values are those found in the value set expansion's 'code' elements.) However, it allows for the set of allowed codes to be maintained as an expression such as "all medications from SNOMED CT", automatically adjusting as the set of matching codes changes based on the evolution of the code system. As such, answerValueSet is appropriate when the set of codes is large or potentially dynamic and enumerating all the possible choices within the Questionnaire does not make sense. To have tighter control of the set of answers allowed for the question, consider making the reference to the ValueSet version-specific. To really lock down the set of codes, the value set should itself tie itself to specific versions of the underlying code systems and/or specify a lockedDate.

answerValueSet also allows for the possibility of sharing a set of answers across multiple questions within a single Questionnaire. Sharing the set of allowed answers simplifies maintenance and ensures consistency across questions. This can be important when representing choices as columns or rows in a table (see itemControl). If appropriate, the ValueSet can be nested inside the Questionnaire as a contained resource. This should only be done if the ValueSet is intrinsically tied to the Questionnaire and should only ever be edited in the context of the Questionnaire. Such ValueSets will not be available for use elsewhere.

answerOption works well when there is a small (2 - 20ish) number of choices and if the question type is integer, date, time or reference. The set of options is maintained independently for each question.

The third mechanism for capturing the allowed set of answers is by using the answerExpression extension. This extension allows specifying a FHIR Query, FHIRPath, or CQL expression that resolves to a list of permitted answers for a question item. The expression must evaluate to a collection of elements with the same type as the item.type or, if the type was Reference, to resources allowed as the referenced type. For more details on answerExpression, click here.

These three mechanisms are mutually exclusive. Only one SHOULD appear on the same question. If answerOption appears, there SHOULD be more than one repetition of it. A question with a single answerOption will be treated as having a single fixed value.

If the set of choices is restricted using any of these three mechanisms, the use of any other Value Constraint elements is redundant and confusing. Therefore, questions that have 'answerOption', 'answerValueSet' or 'answerExpression' extension SHALL NOT make use of any of the other Value Constraint extensions.

answerValueSet Core question integer example

See discussion above under answerOption.

answerExpression SDC question expression TODO

See discussion above under answerOption. This extension is described in detail here.

required Questionnaire group, question boolean example

For an 'active' (see enableWhen) group or question, this indicates whether the element must appear in the corresponding QuestionnaireResponse. If 'true', it means that at least one answer must be provided for the question, or for a group, that at least one question descended from the group must have an answer. Note that if a group is not included, there's no need to include items within the group, even if they are marked as 'required'. Display items should never be marked as 'required' and if they are, it has no meaning. This element can also impact rendering. To further constrain the minimum number of elements required, see the minOccurs extension.

Note that, depending on entryMode, users may be able to 'skip' required questions and come back to them later. However, the status of a QuestionnaireResponse SHALL NOT change to 'completed' until all enabled 'required' items are populated.

repeats Questionnaire group, question boolean example

For groups, a 'repeats' value of 'true' means that the QuestionnaireResponse can contain multiple item repetitions that correspond to the same linkId. For questions, it means that the question with the same linkId can have more than one answer. (I.e. there will not be multiple repetitions of the question item in the QuestionnaireResponse, but instead the one corresponding question item can have multiple answers. Display items should never be marked as 'repeats' and if they are, it has no meaning. This element can also impact rendering. To constrain the minimum number of elements permitted for a repeating element, see the minOccurs extension.

readOnly Questionnaire question boolean example

If present indicates that the answer to the question is not allowed to be edited or changed by someone completing the questionnaire. This can be used for information that is either set to a fixed value by the form designer using the initial element or something that is calculated using the initialExpression during load or calculatedExpression based on other information in the QuestionnaireResponse. This element can also impact rendering. Elements marked as 'readOnly' are intended to be displayed to the user filling out the QuestionnaireResponse. For information that should not be seen by the user, use the hidden extension.

minOccurs Questionnaire group, question integer example

The required element allows distinguishing items that are optional (minOccurs=0) from those that are required (minOccurs=1). However, for elements where repeats is true, it's sometimes necessary to indicate that multiple repetitions are required. For example, a question might ask the user to "select your top 3 choices" and want to enforce that at least 3 choices had been chosen. The minOccurs extension allows such rules to be enforced. Using the cqf-calculatedValue extension or the cqf-expression extension, the minimum number of repetitions can also be made dynamic. For example, one question might ask "How many brothers and sisters did you have?" while a subsequent repeating group captures information about each sibling. The Questionnaire could enforce that the number of group repetitions matched the number of siblings indicated by setting minOccurs and maxOccurs.

This element SHALL only be set for an item where both required and repeats are true.

Note that, depending on entryMode, users may be able to 'skip' questions that do not meet the minimum number of repetitions and come back to them later. However, the status of a QuestionnaireResponse SHALL NOT change to 'completed' until all enabled items have their minOccurs requirement met.

maxOccurs Questionnaire group, question integer example

The repeats element allows indicating that an item is permitted to repeat, but places no limits on the number of times the group can appear in the response or the number of answers a question can have. This extension allows a limit to be imposed. For example, a question might indicate "choose no more than 3". Using the cqf-calculatedValue extension or the cqf-expression extension, the maximum number of repetitions can also be made dynamic as described in minOccurs.

This element SHALL only be set for an item where repeats are true.

optionExclusive Questionnaire Questionnaire.item.answerOption boolean example

For questions with multiple answerOption elements that are allowed to have multiple answers (repeats=true), if this extension is true for a specific answerOption, it indicates that once the user selects this answerOption, no other answers may be selected. This extension is ideal for a multi-select question that has an option that is not compatible with all the others. Examples of these exclusive options are "None of the above", "All of the above", "Don't know", or "Not applicable".

This element is only relevant for an item where repeats are true.

unitOption Questionnaire Quantity Coding example

Just as the answerOption and answerValueSet elements support identifying the specific answers that can be selected, the unitOption and unitValueSet extensions allow defining the choices for the unit of for a question with the 'quantity' type. The behavior and trade-offs between enumerating the options and referencing a re-useable value set are the same for enforcing units as they are for enforcing answer choices and the extensions for units work the same way as those core elements.

To set a default from among the candidate units, it's possible to use the initial element.

unitValueSet Questionnaire Quantity Reference(ValueSet) example

See unitOption for discussion.

questionnaire-referenceResource Questionnaire Reference code example

Questions with a type of 'Reference' have no constraints on what the reference is expected to point to. This extension allows constraining the content to only resources of a specific type. If multiple extensions are present, it indicates that the resource must come from one of them. Further constraining can be done with the referenceProfile and/or candidateExpression extensions.

referenceProfile Questionnaire Reference canonical(StructureDefinition) example

This extension asserts that resources selected as the answer to the question must be valid against the specified profile. It is tighter than the referenceResource extension (and thus there's no need to specify a referenceResource if referenceProfile is defined). If multiple referenceProfiles are listed, then the selected resource must be valid against at least one of the profiles. The Form Filler can choose to use the profiles as filter criteria in a search, but not all systems will necessarily support search by profile or will support the listed profile(s). Thus, a fallback to evaluating candidates against the profile(s) and filtering the list to exclude those that are not should also be supported. More sophisticated querying is supported by the candidateExpression extension.

candidateExpression SDC question expression example

Described in detail here. A FHIRPath or CQL Expression, or FHIR Query that resolves to a list of candidate answers (usually based on other answers in the questionnaire or based on information within the health record) for the question item or that establishes context for a group item.

lookupQuestionnaire Questionnaire Reference canonical(Questionnaire) example

In some cases, the target resource for the answer to a Reference question might not exist and the user might need to create it. This can be done by displaying a Questionnaire that supports defining the content of the target resource and using the Data Extraction mechanism to convert the resulting QuestionnaireResponse into a FHIR resource of the appropriate type. The resulting resource can either be stored on the target server or passed as a contained resource within the referencing QuestionnaireResponse. This extension defines the Questionnaire that should be used for the purpose of creating the necessary resource. When this is done, the Questionnaire should be designed such that the resulting resource instance will comply with any declared referenceProfile.

Calculations

These extensions support performing calculations as part of completing a QuestionnaireResponse. This might be to set the value of a readOnly question using calculatedExpression. They can also set the value of other control fields, such as minValue, maxValue, minOccurs or maxOccurs They are all described in detail on the Using Expressions page. They are summarized here to indicate their use as part of defining form behavior. Many of these extensions are also relevant when performing Questionnaire Population and/or Data Extraction.

Code Source Location Data Type Example
cqf-library Core root canonical(Library) example

Described in detail here. This extension allows the expressions-based extensions below to leverage shared libraries of FHIR queries, CQL and FHIRPath.

launchContext SDC root complex example

Described in detail here. This extension allows the Questionnaire to be passed context information that can be used within lookupQuestionnaires, to determine which items to enable using enableWhenExpression (e.g. suppress certain questions if the submitter is a specified gender or age), or to help determine the answer to a question, though that falls more within the space of Questionnaire Population.

variable Core root, item Expression example

Described in detail here. This extension allows the calculation of information based on descendant question answers (and other variables or launchContext elements) that can then be referenced by extensions on other items that do not have the same scope - and thus don't have access to the same question answers.

initialExpression SDC question Expression example

Described in detail here. This extension allows the initial value of an element to be set based on an expression. For example, defaulting a date to the current date. (It can also be used to set an answer based on launch context or information queried from external sources, though that falls more within the domain of Questionnaire Population.)

calculatedExpression SDC question Expression example

Described in detail here. This extension allows answers to questions (generally readOnly or hidden ones) to be calculated based on answers to other questions. For example, the determination of a score.

cqf-calculatedValue Core minOccurs, maxOccurs, minValue, maxValue string example

This extension can make some of the control values of the Questionnaire dynamic. For the SDC implementation guide, the recommended locations for use are minOccurs, maxOccurs, minValue, and maxValue. However, in principle, they can be used for other elements as well. Even the text of a question could be dynamic, though obviously that could impact the consistency and comparability of data calculated using the Questionnaire.

cqf-expression Core minOccurs, maxOccurs, required, repeats, readOnly , answerValueSet Expression example

Same as cqf-calculatedValue, this extension can make some of the control values of the Questionnaire dynamic. It allows an expression to provide the value for the element on which it appears. For the SDC implementation guide, the recommended locations for use are minOccurs, maxOccurs, required, repeats, readOnly, answerValueSet. However, in principle, they can be used for other elements as well.

Other Control

These are additional elements and extensions relevant to controlling the completion of the QuestionnaireResponse that do not fit into the previous categories.

Code Source Location Data Type Example
entryMode SDC Questionnaire code example

This indicates how the questions in the form should be displayed to the user and what type of navigation control they should have to look at (and change) other questions:

  • Only one question displayed at a time; no back-tracking or editing prior questions
  • Backtracking and editing is allowed, but future questions are only enabled once a question has been answered (or explicitly skipped)
  • All enabled questions are displayed at once and the user can fill things in in whatever order they see fit
initial N/A item complex example

Establishes the default answer for a question. If the user does not change the value, this is what will appear in the completed QuestionnaireResponse. For choice and open-choice questions, initial.value SHALL be one (or more) of the enumerated answer options provided by answerOption, answerValueSet, or answerExpression extension.

Note that 'initial' does not have to specify all properties. For example, it can be used to select a default unit of measure for a quantity, or potentially (depending on user interface), a default media type for an attachment. To do this, simply specify the property being defaulted (e.g. Quantity.code and Quantity.system) while omitting the remainder.

enableWhen N/A item complex example

This controls which questions, groups and even display items should be displayed based on answers to other questions within the response. An item is 'enabled' based on whether the referenced questions have one (or more) of the answers as specified by the enableWhen element. If multiple enableWhen elements are present on an item, the interpretation is governed by the enableBehavior element. Elements that are not enabled should either be hidden from the user or at least grayed-out and non-selectable and non-editable. Any behavioral constraints associated with non-enabled elements (such as required or minOccurs are ignored and no answers are stored for non-enabled content.

For more sophisticated enableWhen behavior, the enableWhenExpression element can be used instead.

enableBehavior N/A item code example

This determines the interpretation of multiple enableWhen elements. If set to 'all', then the item will only be enabled if all the enableWhen conditions are met. If set to 'any', the item will be enabled if any of the enableWhen conditions are met.

enableWhenExpression SDC item code example

Described in detail here. This serves the same purpose as enableWhen, it controls whether an item should be 'enabled' or not, but can handle more sophisticated circumstances than that extension. For example, it is possible to calculate a score based on the answer to several questions and then enable other questions based on the score. It's also possible to enable or disable questions based on data passed in as context or retrieved from queries.

usageMode Questionnaire item code example

This extension is similar to enableWhen in that it enables or disables elements within the Questionnaire. However, rather than being driven by data within the form or queried or passed from outside, it is instead driven by how the QuestionnaireResponse is being used. Specifically, it allows certain elements to be enabled or disabled based on whether the form is being completed or whether it's being rendered after being completed. When being rendered after completion, it also allows questions and groups to be suppressed if they are 'empty'. For example, the extension might hide data entry instructions when displaying a completed form and might hide 'interpretation' instructions when performing data entry. It might also hide a score during data entry, but make it visible once the form is ready to be reviewed.

constraint Questionnaire Questionnaire, item complex example

This allows assertion of constraints across an entire questionnaire or across any item with child items. All 'error' constraints SHALL evaluate to 'true' before setting a QuestionnaireResponse to complete. For example, it could be used to require that either the patient identifier or birth date must be specified, that at least 6 of the questions from question 10 through 20 must be answered, or that the sum of questions 1 through 5 must equal exactly 100. The human field SHOULD be set to inform the user what to do. The expression is written in FHIRPath and has access to the additional FHIRPath capabilities defined in Using Expressions.

endpoint SDC root uri example

This allows a Questionnaire to indicate the URL of the Form Receiver it should be posted to when complete. (Note that it is up to the Form Filler and/or the user to determine whether to post to the indicated endpoint or to store the form elsewhere - or to do both.)

signatureRequired Questionnaire root, group, question CodeableConcept example

This allows a form to indicate whether the form must be signed on completion or whether specified questions or answers themselves must be signed. If a signature is required, elements present in the QuestionnaireResponse must have signatures before marking the QuestionnaireResponse as complete. Signature can be as simple as providing the user's initials to confirm that they've verified and agree with the answer, or it could mean a full digital signature. This extension will tend to be used on Questionnaires that result in legal documents.

ordinalValue Core Coding, Questionnaire.item.answerOption, CodeSystem.concept, ValueSet.compose.include.concept decimal example

This extension allows a choice element (whether in a question-specific answerOption or in the code system and value set pointed to by answerValueSet) to have an associated numeric weighting. This numeric weighting can be captured as part of the QuestionnaireResponse.item.answer.valueCoding. More importantly it can be referenced by expressions used to calculate scores using calculatedExpression and/or to control the display of elements using enableWhenExpression. For example, the answer 'never' might have an ordinal value of 0, the answer occasionally might have a value of 1, the answer of weekly 2 and daily 4. The answer given would then be incorporated in an overall risk or diagnostic score.