Aidbox Forms: Populate & Extract
How to create smart forms that may be prefilled with existing data, may update or create new resources
10 cells · updated Jun 27, 2024
Introduction
Aidbox Forms let you populate forms with previous measurements or already existing data. Also, you can update existing data and save new measurements.
Populate
Aidbox forms supports two ways of populating questionnaire:
Extraction
Aidbox forms suppotrs two-ways of extraction captured date to FHIR resources
In this tutorial we will create some resources to demonstrate how population works and how extract can be used to create and update resources.
1. Prepare data
Let's create Patient, Observations and AllergyIntolerance
POST /
Content-type: application/yaml
resourceType: Bundle
type: transaction
entry:
- resource:
resourceType: Patient
id: john
name:
- given:
- John
family: Doe
birthDate: '1968-09-11'
request:
method: POST
url: /Patient
- resource:
value:
Quantity:
unit: kg
value: 105
resourceType: Observation
status: final
effective:
dateTime: '2024-06-27T11:10:14.475Z'
code:
coding:
- code: 29463-7
system: http://loinc.org
display: Body weight
subject:
id: john
resourceType: Patient
request:
method: POST
url: /Observation
- resource:
value:
Quantity:
unit: m
value: 1.78
resourceType: Observation
status: final
effective:
dateTime: '2024-06-27T11:10:14.475Z'
code:
coding:
- code: 8302-2
system: http://loinc.org
display: Body height
subject:
id: john
resourceType: Patient
request:
method: POST
url: /Observation
- resource:
patient:
id: john
resourceType: Patient
category:
- food
clinicalStatus:
coding:
- code: active
system: http://terminology.hl7.org/CodeSystem/allergyintolerance-clinical
display: Active
resourceType: AllergyIntolerance
request:
method: POST
url: /AllergyIntolerancetype: transaction-response
resourceType: Bundle
entry:
- resource:
name:
- given: [John]
family: Doe
birthDate: '1968-09-11'
id: john
resourceType: Patient
meta: {lastUpdated: '2024-06-27T11:28:07.857560Z', createdAt: '2024-06-27T11:28:07.857560Z', versionId: '181'}
response: {etag: '181', location: /Patient/john/_history/181, status: '201', lastModified: '2024-06-27T11:28:07.857560Z'}
- resource:
code:
coding:
- {code: 29463-7, system: 'http://loinc.org', display: Body weight}
value:
Quantity: {unit: kg, value: 105}
status: final
subject: {id: john, resourceType: Patient}
effective: {dateTime: '2024-06-27T11:10:14.475Z'}
id: b62c62c1-c10f-4b05-9fc2-d30f05812b35
resourceType: Observation
meta: {lastUpdated: '2024-06-27T11:28:07.857560Z', createdAt: '2024-06-27T11:28:07.857560Z', versionId: '182'}
response: {etag: '182', location: /Observation/b62c62c1-c10f-4b05-9fc2-d30f05812b35/_history/182, status: '201', lastModified: '2024-06-27T11:28:07.857560Z'}
- resource:
code:
coding:
- {code: 8302-2, system: 'http://loinc.org', display: Body height}
value:
Quantity: {unit: m, value: 1.78}
status: final
subject: {id: john, resourceType: Patient}
effective: {dateTime: '2024-06-27T11:10:14.475Z'}
id: 2db90741-7cb6-4f50-8e9f-571adcfa7935
resourceType: Observation
meta: {lastUpdated: '2024-06-27T11:28:07.857560Z', createdAt: '2024-06-27T11:28:07.857560Z', versionId: '183'}
response: {etag: '183', location: /Observation/2db90741-7cb6-4f50-8e9f-571adcfa7935/_history/183, status: '201', lastModified: '2024-06-27T11:28:07.857560Z'}
- resource:
patient: {id: john, resourceType: Patient}
category: [food]
clinicalStatus:
coding:
- {code: active, system: 'http://terminology.hl7.org/CodeSystem/allergyintolerance-clinical', display: Active}
id: f6a8ef20-735b-47eb-b8dc-b5cefc1db676
resourceType: AllergyIntolerance
meta: {lastUpdated: '2024-06-27T11:28:07.857560Z', createdAt: '2024-06-27T11:28:07.857560Z', versionId: '184'}
response: {etag: '184', location: /AllergyIntolerance/f6a8ef20-735b-47eb-b8dc-b5cefc1db676/_history/184, status: '201', lastModified: '2024-06-27T11:28:07.857560Z'}
id: '185'
2. Create Questionnaire
This Questionnaire contains 3 sections:
-
General Patient Info
This section will be populated from Patient resource and will update Patient on extract
-
Height & Weight
This section uses Observation-based approach to populate items and extract
-
Allergies
This section uses Expression-based approach to populate
AllergyIntoleranceresources and Definition-based approach to update existing allergies and add new
POST /Questionnaire
Content-type: application/yaml
url: http://forms.aidbox.io/questionnaire/patient-test-form
item:
- item:
- text: Given
type: string
linkId: given
extension:
- url: http://aidbox.io/questionnaire-itemColumnSize
value:
integer: 4
- url: http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-initialExpression
value:
Expression:
language: text/fhirpath
expression: '%patient.name.given'
definition: Patient.name.given
- text: Family
type: string
linkId: 9FwYzNVk
extension:
- url: http://aidbox.io/questionnaire-itemColumnSize
value:
integer: 4
- url: http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-initialExpression
value:
Expression:
language: text/fhirpath
expression: '%patient.name.family'
definition: Patient.name.family
- text: Date
type: date
linkId: birthDate
extension:
- url: http://aidbox.io/questionnaire-itemColumnSize
value:
integer: 4
- url: http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-initialExpression
value:
Expression:
language: text/fhirpath
expression: '%patient.birthDate'
definition: Patient.birthDate
text: General
type: group
linkId: general
extension:
- url: http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-itemPopulationContext
value:
Expression:
name: patient
language: application/x-fhir-query
expression: /Patient/{{%subject.id}}
- url: http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-itemExtractionContext
value:
Expression:
language: application/x-fhir-query
expression: /Patient/{{%resource.subject.id}}
- item:
- code:
- code: 8302-2
system: http://loinc.org
display: Body height
text: Height
type: quantity
linkId: height
extension:
- url: http://hl7.org/fhir/StructureDefinition/questionnaire-unitOption
value:
Coding:
display: m
- url: http://aidbox.io/questionnaire-itemColumnSize
value:
integer: 4
- url: http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-observationExtract
value:
boolean: true
- url: http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-observationLinkPeriod
value:
Duration:
code: a
value: 1
system: ucum
- code:
- code: 29463-7
system: http://loinc.org
display: Body height
text: Weight
type: quantity
linkId: weight
extension:
- url: http://hl7.org/fhir/StructureDefinition/questionnaire-unitOption
value:
Coding:
display: kg
- url: http://aidbox.io/questionnaire-itemColumnSize
value:
integer: 4
- url: http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-observationLinkPeriod
value:
Duration:
code: a
value: 1
system: ucum
- url: http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-observationExtract
value:
boolean: true
- code:
- code: 39156-5
system: http://loinc.org
display: Body height
text: BMI
type: decimal
linkId: bmi
extension:
- url: http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-calculatedExpression
value:
Expression:
language: text/fhirpath
expression: "%resource.repeat(item).where(linkId='weight').answer.value.value / \n%resource.repeat(item).where(linkId='height').answer.value.value.power(2)"
- url: http://aidbox.io/questionnaire-itemColumnSize
value:
integer: 4
text: Height & Weight
type: group
linkId: hZsHDBA2
- item:
- text: (id)
type: string
linkId: id
extension:
- url: http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-initialExpression
value:
Expression:
language: text/fhirpath
expression: '%allergies.id'
- url: http://hl7.org/fhir/StructureDefinition/questionnaire-hidden
value:
boolean: true
definition: AllergyIntolerance.id
- text: (pt. reference)
type: reference
linkId: reference
extension:
- url: http://hl7.org/fhir/StructureDefinition/questionnaire-hidden
value:
boolean: true
- url: http://hl7.org/fhir/StructureDefinition/questionnaire-referenceResource
- url: http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-calculatedExpression
value:
Expression:
language: text/fhirpath
expression: '%resource.subject'
definition: AllergyIntolerance.patient
- text: Status
type: choice
linkId: FmqK7esk
extension:
- url: http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-initialExpression
value:
Expression:
language: text/fhirpath
expression: '%allergies.clinicalStatus.coding.first()'
definition: AllergyIntolerance.clinicalStatus.coding
answerOption:
- value:
Coding:
code: active
system: http://terminology.hl7.org/CodeSystem/allergyintolerance-clinical
display: Active
- value:
Coding:
code: inactive
system: http://terminology.hl7.org/CodeSystem/allergyintolerance-clinical
display: Inactive
- value:
Coding:
code: resolved
system: http://terminology.hl7.org/CodeSystem/allergyintolerance-clinical
display: Resolved
- text: Category
type: choice
linkId: RZsAnKZH
extension:
- url: http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-initialExpression
value:
Expression:
language: text/fhirpath
expression: '%qitem.answerOption.valueCoding.where(code=%allergies.category)'
definition: AllergyIntolerance.category
answerOption:
- value:
Coding:
code: food
system: http://hl7.org/fhir/allergy-intolerance-category
display: Food
- value:
Coding:
code: medication
system: http://hl7.org/fhir/allergy-intolerance-category
display: Medication
- value:
Coding:
code: environment
system: http://hl7.org/fhir/allergy-intolerance-category
display: Environment
- value:
Coding:
code: biologic
system: http://hl7.org/fhir/allergy-intolerance-category
display: Biologic
text: Allergies
type: group
linkId: allergies
repeats: true
extension:
- url: http://hl7.org/fhir/StructureDefinition/questionnaire-itemControl
value:
CodeableConcept:
coding:
- code: gtable
- url: http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-itemPopulationContext
value:
Expression:
name: allergies
language: application/x-fhir-query
expression: /AllergyIntolerance?.patient.id={{%subject.id}}
- url: http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-itemExtractionContext
value:
Expression:
language: application/x-fhir-query
expression: /AllergyIntolerance?.patient.id={{%resource.subject.id}}
title: Patient Info
id: patient-info
status: draft
resourceType: Questionnaireurl: http://forms.aidbox.io/questionnaire/patient-test-form
item:
- item:
- text: Given
type: string
linkId: given
extension:
- url: http://aidbox.io/questionnaire-itemColumnSize
value: {integer: 4}
- url: http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-initialExpression
value:
Expression: {language: text/fhirpath, expression: '%patient.name.given'}
definition: Patient.name.given
- text: Family
type: string
linkId: 9FwYzNVk
extension:
- url: http://aidbox.io/questionnaire-itemColumnSize
value: {integer: 4}
- url: http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-initialExpression
value:
Expression: {language: text/fhirpath, expression: '%patient.name.family'}
definition: Patient.name.family
- text: Date
type: date
linkId: birthDate
extension:
- url: http://aidbox.io/questionnaire-itemColumnSize
value: {integer: 4}
- url: http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-initialExpression
value:
Expression: {language: text/fhirpath, expression: '%patient.birthDate'}
definition: Patient.birthDate
text: General
type: group
linkId: general
extension:
- url: http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-itemPopulationContext
value:
Expression: {name: patient, language: application/x-fhir-query, expression: '/Patient/{{%subject.id}}'}
- url: http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-itemExtractionContext
value:
Expression: {language: application/x-fhir-query, expression: '/Patient/{{%resource.subject.id}}'}
- item:
- code:
- {code: 8302-2, system: 'http://loinc.org', display: Body height}
text: Height
type: quantity
linkId: height
extension:
- url: http://hl7.org/fhir/StructureDefinition/questionnaire-unitOption
value:
Coding: {display: m}
- url: http://aidbox.io/questionnaire-itemColumnSize
value: {integer: 4}
- url: http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-observationExtract
value: {boolean: true}
- url: http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-observationLinkPeriod
value:
Duration: {code: a, value: 1, system: ucum}
- code:
- {code: 29463-7, system: 'http://loinc.org', display: Body height}
text: Weight
type: quantity
linkId: weight
extension:
- url: http://hl7.org/fhir/StructureDefinition/questionnaire-unitOption
value:
Coding: {display: kg}
- url: http://aidbox.io/questionnaire-itemColumnSize
value: {integer: 4}
- url: http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-observationLinkPeriod
value:
Duration: {code: a, value: 1, system: ucum}
- url: http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-observationExtract
value: {boolean: true}
- code:
- {code: 39156-5, system: 'http://loinc.org', display: Body height}
text: BMI
type: decimal
linkId: bmi
extension:
- url: http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-calculatedExpression
value:
Expression:
language: text/fhirpath
expression: "%resource.repeat(item).where(linkId='weight').answer.value.value / \n%resource.repeat(item).where(linkId='height').answer.value.value.power(2)"
- url: http://aidbox.io/questionnaire-itemColumnSize
value: {integer: 4}
text: Height & Weight
type: group
linkId: hZsHDBA2
- item:
- text: (id)
type: string
linkId: id
extension:
- url: http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-initialExpression
value:
Expression: {language: text/fhirpath, expression: '%allergies.id'}
- url: http://hl7.org/fhir/StructureDefinition/questionnaire-hidden
value: {boolean: true}
definition: AllergyIntolerance.id
- text: (pt. reference)
type: reference
linkId: reference
extension:
- url: http://hl7.org/fhir/StructureDefinition/questionnaire-hidden
value: {boolean: true}
- {url: 'http://hl7.org/fhir/StructureDefinition/questionnaire-referenceResource'}
- url: http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-calculatedExpression
value:
Expression: {language: text/fhirpath, expression: '%resource.subject'}
definition: AllergyIntolerance.patient
- text: Status
type: choice
linkId: FmqK7esk
extension:
- url: http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-initialExpression
value:
Expression: {language: text/fhirpath, expression: '%allergies.clinicalStatus.coding.first()'}
definition: AllergyIntolerance.clinicalStatus.coding
answerOption:
- value:
Coding: {code: active, system: 'http://terminology.hl7.org/CodeSystem/allergyintolerance-clinical', display: Active}
- value:
Coding: {code: inactive, system: 'http://terminology.hl7.org/CodeSystem/allergyintolerance-clinical', display: Inactive}
- value:
Coding: {code: resolved, system: 'http://terminology.hl7.org/CodeSystem/allergyintolerance-clinical', display: Resolved}
- text: Category
type: choice
linkId: RZsAnKZH
extension:
- url: http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-initialExpression
value:
Expression: {language: text/fhirpath, expression: '%qitem.answerOption.valueCoding.where(code=%allergies.category)'}
definition: AllergyIntolerance.category
answerOption:
- value:
Coding: {code: food, system: 'http://hl7.org/fhir/allergy-intolerance-category', display: Food}
- value:
Coding: {code: medication, system: 'http://hl7.org/fhir/allergy-intolerance-category', display: Medication}
- value:
Coding: {code: environment, system: 'http://hl7.org/fhir/allergy-intolerance-category', display: Environment}
- value:
Coding: {code: biologic, system: 'http://hl7.org/fhir/allergy-intolerance-category', display: Biologic}
text: Allergies
type: group
linkId: allergies
repeats: true
extension:
- url: http://hl7.org/fhir/StructureDefinition/questionnaire-itemControl
value:
CodeableConcept:
coding:
- {code: gtable}
- url: http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-itemPopulationContext
value:
Expression: {name: allergies, language: application/x-fhir-query, expression: '/AllergyIntolerance?.patient.id={{%subject.id}}'}
- url: http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-itemExtractionContext
value:
Expression: {language: application/x-fhir-query, expression: '/AllergyIntolerance?.patient.id={{%resource.subject.id}}'}
title: Patient Info
status: draft
id: patient-info
resourceType: Questionnaire
meta: {lastUpdated: '2024-06-27T13:48:49.177920Z', createdAt: '2024-06-27T13:48:49.177920Z', versionId: '191'}
3. Populate Questionnaire
Now, we are ready to see how to populate Questionnaire with existing data. Let's call $populate operation to get QuestionnarieResponse with prefilled items:
- general patient info items were filled from Patient resource
- width and height items were filled from Observation resources
- allergies info was populated from AllergyIntolerance resource
POST /Questionnaire/patient-info/$populate
content-type: application/yaml
resourceType: Parameters
parameter:
- name: subject
value:
Reference:
id: john
resourceType: Patient
resourceType: Parameters
parameter:
- name: response
resource:
resourceType: QuestionnaireResponse
questionnaire: http://forms.aidbox.io/questionnaire/patient-test-form
status: in-progress
subject: {id: john, resourceType: Patient}
item:
- linkId: general
text: General
item:
- linkId: given
text: Given
answer:
- {valueString: Morgan}
- linkId: 9FwYzNVk
text: Family
answer:
- {valueString: James}
- linkId: birthDate
text: Date
answer:
- {valueDate: '1996-12-05'}
- linkId: hZsHDBA2
text: Height & Weight
item:
- linkId: height
text: Height
answer:
- valueQuantity: {unit: m, value: 1.78}
- linkId: weight
text: Weight
answer:
- valueQuantity: {unit: kg, value: 105}
- {linkId: bmi, text: BMI}
- linkId: allergies
text: Allergies
item:
- linkId: id
text: (id)
answer:
- {valueString: f6a8ef20-735b-47eb-b8dc-b5cefc1db676}
- {linkId: reference, text: (pt. reference)}
- linkId: FmqK7esk
text: Status
answer:
- valueCoding: {code: active, system: 'http://terminology.hl7.org/CodeSystem/allergyintolerance-clinical', display: Active}
- linkId: RZsAnKZH
text: Category
answer:
- valueCoding: {code: food, system: 'http://hl7.org/fhir/allergy-intolerance-category', display: Food}
4. Extraction
When form is filled, we want to extract some info into new resources or update existing ones. Here we send our filled QuestionnarieResponse to $extract operation to get Bundle.
POST /QuestionnaireResponse/$extract
content-type: application/yaml
resourceType: Parameters
parameter:
- name: questionnaire-response
resource:
item:
- item:
- text: Given
answer:
- value:
string: Jane
linkId: given
- text: Family
answer:
- value:
string: Doe
linkId: 9FwYzNVk
- text: Date
answer:
- value:
date: '2003-08-11'
linkId: birthDate
text: General
linkId: general
- item:
- text: Height
answer:
- value:
Quantity:
unit: m
value: 1.56
linkId: height
- text: Weight
answer:
- value:
Quantity:
unit: kg
value: 50
linkId: weight
- text: BMI
answer:
- value:
decimal: 20.5456936226167
linkId: bmi
text: Height & Weight
linkId: hZsHDBA2
- item:
- text: (pt. reference)
answer:
- value:
Reference:
id: john
resourceType: Patient
linkId: reference
- text: Status
answer:
- value:
Coding:
code: active
system: http://terminology.hl7.org/CodeSystem/allergyintolerance-clinical
display: Active
linkId: FmqK7esk
- text: Category
answer:
- value:
Coding:
code: medication
system: http://hl7.org/fhir/allergy-intolerance-category
display: Medication
linkId: RZsAnKZH
text: Allergies
linkId: allergies
- item:
- text: (pt. reference)
answer:
- value:
Reference:
id: john
resourceType: Patient
linkId: reference
- text: Status
answer:
- value:
Coding:
code: active
system: http://terminology.hl7.org/CodeSystem/allergyintolerance-clinical
display: Active
linkId: FmqK7esk
- text: Category
answer:
- value:
Coding:
code: food
system: http://hl7.org/fhir/allergy-intolerance-category
display: Food
linkId: RZsAnKZH
text: Allergies
linkId: allergies
status: completed
subject:
id: john
resourceType: Patient
authored: '2024-06-27T13:59:19.317Z'
questionnaire: http://forms.aidbox.io/questionnaire/patient-test-form
resourceType: QuestionnaireResponseresourceType: Parameters
parameter:
- name: return
resource:
resourceType: Bundle
type: transaction
entry:
- resource:
name:
- given: [Jane]
family: Doe
birthDate: '2003-08-11'
id: john
resourceType: Patient
request: {method: PUT, url: /Patient/john}
- resource:
resourceType: Observation
status: final
code:
coding:
- {code: 8302-2, system: 'http://loinc.org', display: Body height}
subject: {id: john, resourceType: Patient}
value:
Quantity: {unit: m, value: 1.56}
encounter: {}
effective: {dateTime: '2024-06-27T13:59:19.317Z'}
id: cf76156a-b7a9-4693-ba67-e14988a74412
request: {method: POST, url: /Observation}
- resource:
resourceType: Observation
status: final
code:
coding:
- {code: 29463-7, system: 'http://loinc.org', display: Body height}
subject: {id: john, resourceType: Patient}
value:
Quantity: {unit: kg, value: 50}
encounter: {}
effective: {dateTime: '2024-06-27T13:59:19.317Z'}
id: 387963a9-fb3f-42b2-b711-b20bfc69e19b
request: {method: POST, url: /Observation}
- resource:
patient: {id: john, resourceType: Patient}
category: [medication]
clinicalStatus:
coding:
- {code: active, system: 'http://terminology.hl7.org/CodeSystem/allergyintolerance-clinical', display: Active}
id: f6a8ef20-735b-47eb-b8dc-b5cefc1db676
resourceType: AllergyIntolerance
request: {method: PUT, url: /AllergyIntolerance/f6a8ef20-735b-47eb-b8dc-b5cefc1db676}
- resource:
resourceType: AllergyIntolerance
patient: {id: john, resourceType: Patient}
clinicalStatus:
coding:
- {code: active, system: 'http://terminology.hl7.org/CodeSystem/allergyintolerance-clinical', display: Active}
category: [food]
id: b66c832c-2469-466c-80d0-86918672a9a0
request: {method: POST, url: /AllergyIntolerance}
- name: issues
resource:
resourceType: OperationOutcome
issues:
- {severity: warning, code: value, expression: QuestionnaireResponse.id, diagnostics: Provenance cannot be created due to lack id information}
- {severity: warning, code: value, expression: QuestionnaireResponse.author, diagnostics: Provenance cannot be created due to lack of author information}
Final
As you see, with Aidbox forms you can create forms that can be prefilled with existing data and after capturing needed data you can update or create any FHIR resources.