stanfordbdhg / researchkitonfhir Goto Github PK
View Code? Open in Web Editor NEWHL7 FHIR Structured Data Capture with ResearchKit on iOS
Home Page: https://swiftpackageindex.com/StanfordBDHG/ResearchKitOnFHIR/documentation
License: MIT License
HL7 FHIR Structured Data Capture with ResearchKit on iOS
Home Page: https://swiftpackageindex.com/StanfordBDHG/ResearchKitOnFHIR/documentation
License: MIT License
I've noticed an issue where custom error messages for both Number and Text type questions in our survey forms aren't being displayed as expected. While the validations are functioning correctly, the custom error messages we've set up arenβt showing up when a user fails to meet the validation criteria.
To give you a better idea, hereβs how you can reproduce the issue:
{
"title": "Test custom error message",
"resourceType": "Questionnaire",
"language": "en-US",
"status": "draft",
"publisher": "Stanford Biodesign Digital Health",
"meta": {
"profile": [
"http://spezi.health/fhir/StructureDefinition/sdf-Questionnaire"
],
"tag": [
{ "system": "urn:ietf:bcp:47", "code": "en-US", "display": "English" }
]
},
"useContext": [
{
"code": {
"system": "http://hl7.org/fhir/ValueSet/usage-context-type",
"code": "focus",
"display": "Clinical Focus"
},
"valueCodeableConcept": {
"coding": [
{
"system": "urn:oid:2.16.578.1.12.4.1.1.8655",
"display": "Test custom error message"
}
]
}
}
],
"contact": [{ "name": "http://spezi.health" }],
"subjectType": ["Patient"],
"url": "http://spezi.health/fhir/questionnaire/dd859ee0-4e7a-4131-f6fa-2239f0ad08b2",
"item": [
{
"linkId": "282ca91c-5123-4c68-9755-8b5aab297dac",
"type": "integer",
"extension": [
{
"url": "http://hl7.org/fhir/StructureDefinition/minValue",
"valueInteger": 0
},
{
"url": "http://hl7.org/fhir/StructureDefinition/maxValue",
"valueInteger": 10
},
{
"url": "http://ehelse.no/fhir/StructureDefinition/validationtext",
"valueString": "Custom error message..."
}
],
"required": false,
"text": "Please, rate your attention"
},
{
"linkId": "1d0a234f-bbd2-4ef4-8b26-1110cce45efe",
"type": "string",
"text": "Please describe the characteristics of you pain?",
"required": false,
"extension": [
{
"url": "http://ehelse.no/fhir/StructureDefinition/validationtext",
"valueString": "Custom error message..."
},
{
"url": "http://hl7.org/fhir/StructureDefinition/regex",
"valueString": "^\\s*\\S+(\\s+\\S+){0,2}\\s*$"
}
]
}
]
}
Ideally, when a user inputs data that doesn't meet the validation criteria, our custom error message should be displayed to guide them.
No response
When you create a questionnaire with the Phoenix Questionnaire Builder with a group of required questions, the ResearchKit view is skippable (e.g., the Skip button is shown).
QuestionnaireView
ResearchKit will render a "Skip" button allowing to skip all required questions.Required questions should not be able to be skipped.
No response
A common survey response type is one in which the participant response belongs to an ordered set of values, e.g.
ResearchKit supports scale responses with the ORKScaleAnswerFormat (for integers) and the ORKTextScaleAnswerFormat, both of a which display a slider in the user interface.
Currently, researchers have to encode such questionnaires as a choice FHIR QuestionnaireItemType, which is converted to a ORKTextChoice ResearchKit type. For example, this would display the options 0-10 as a list of questionnaire options rather than a slider.
Provide support for choice questionnaire items that are on an ordered scale to be mapped to the appropriate ResearchKit type (either ORKScaleAnswerFormat
or ORKTextScaleAnswerFormat
). I am unsure if FHIR differentiates between choice types and ordered choice types, but adding the option to display a slider could be achieved with metadata fields on a ValueSet or on the survey item itself.
Here is an example of a survey item we are currently using in our study:
{
"linkId": "70133a34-8597-4cdf-ec4a-6fb0f8ede585",
"type": "choice",
"text": "Please choose the value that best describes how you felt on average today about your workplace on a scale of 1-7, from I do not fit in my workplace \"0\" to I definitely fit in my workplace \"7\".",
"required": false,
"answerOption":
[
{
"valueCoding":
{
"id": "6f5be914-eee6-458a-805e-a5cd84fac028",
"code": "1",
"system": "urn:uuid:8ac26004-8e67-4916-8f0a-0d70a70626e2",
"display": "1"
}
},
{
"valueCoding":
{
"id": "8004d543-ea5d-4824-8832-9ac81c9c6235",
"code": "2",
"system": "urn:uuid:8ac26004-8e67-4916-8f0a-0d70a70626e2",
"display": "2"
}
},
{
"valueCoding":
{
"id": "2b81b474-9c02-438e-9f22-13be890dc230",
"code": "3",
"system": "urn:uuid:8ac26004-8e67-4916-8f0a-0d70a70626e2",
"display": "3"
}
},
{
"valueCoding":
{
"id": "40845d67-f5b8-49d8-8aac-65913160e7b1",
"code": "4",
"system": "urn:uuid:8ac26004-8e67-4916-8f0a-0d70a70626e2",
"display": "4"
}
},
{
"valueCoding":
{
"id": "6dc6c684-10f1-48c6-9565-647aa2e3fc9e",
"code": "5",
"system": "urn:uuid:8ac26004-8e67-4916-8f0a-0d70a70626e2",
"display": "5"
}
},
{
"valueCoding":
{
"id": "c03a4eda-801a-448c-8ff4-d83f655ba218",
"code": "6",
"system": "urn:uuid:8ac26004-8e67-4916-8f0a-0d70a70626e2",
"display": "6"
}
},
{
"valueCoding":
{
"id": "ee1e918e-1dd5-4133-8f0c-a6cce0303cfd",
"code": "7",
"system": "urn:uuid:8ac26004-8e67-4916-8f0a-0d70a70626e2",
"display": "7"
}
}
]
}
This currently displays as below
It would be nice if this answer could display as a slider
When converting a QuestionnaireItem with QuestionnaireItemType of "group" to an ORKFormStep, the title should contain the "text" element of the QuestionnaireItem, if it is defined.
Some standardized surveys, i.e. the GCS scale found at http://hl7.org/fhir/R4/questionnaire-example-gcs.json.html have only answer choices and no question text. These surveys are not being rendered, because question text is currently not allowed to be empty.
According to FHIR standard URL
attribute has a cardinality between 0..1
. Unfortunately, ResearchKitOnFHIR
is strict in this case and doesn't accept questionnaires without URL
even though the standard is still fulfilled.
Currently, this kind of restriction doesn't exist in equivalent libraries for Android and FE.
Also, there are currently 3rd party services that provide questionnaires without URL and are not presentable by this library.
The best solution to this issue would be to make URL parameter of ORKNavigableOrderedTask
optional.
In this case FHIR URL
serves as an identifier of ORKNavigableOrderedTask
.
Instead of throwing an error, we can put any non-url placeholder - static String
or dynamic- for example UUID
.
In the public var fhirResponse: QuestionnaireResponse
we can put something like:
if let questionnaireURL = questionnaireID.flatMap(URL.init) {
questionnaireResponse.questionnaire = FHIRPrimitive(Canonical(questionnaireURL))
}
Even though, this is a small improvement, it can be a dealbreaker for other people who use this library.
Of course, I can help with the implementation and currently, I'm not aware of any blocker.
Small sidenote: I tried to inject URL to the Questionnaire
but it causes crashes on Android in case you'd want to display responses from iOS on Android. You see, Android compares URL of Questionnaire
vs Responses
. And the discrepancy between these URLs is causing runtime crash on Android.
On certain occasions, some questions that should be displayed based on the answers to previous questions within a questionnaire are inadvertently omitted. This means that while they should appear in the questionnaire flow based on previous answers, these questions are not presented as expected.
This suggests some kind of issue with the navigation logic, probably in the translation of the attributes of the ResearchKit navigation rules.
To verify the situation, UI tests were developed, which were executed in a multi-run test plan obtaining the following results:
This shows that in nine out of every hundred executions, the dependent question was not displayed, even following the same flow.
Although the error rate decreased in this scenario, failures still occurred.
The questionnaire in JSON FHIR format used for the above tests, and with which the incident is being presented, is as follows:
{
"resourceType": "Questionnaire",
"language": "en-US",
"title": "Report on tests",
"status": "draft",
"publisher": "Tester",
"meta": {
"profile": [
"http://spezi.health/fhir/StructureDefinition/sdf-Questionnaire"
],
"tag": [
{ "system": "urn:ietf:bcp:47", "code": "en-US", "display": "English" }
]
},
"useContext": [
{
"code": {
"system": "http://hl7.org/fhir/ValueSet/usage-context-type",
"code": "focus",
"display": "Clinical Focus"
},
"valueCodeableConcept": {
"coding": [
{
"system": "urn:oid:2.16.578.1.12.4.1.1.8655",
"display": "Untitled"
}
]
}
}
],
"contact": [{ "name": "http://testing.test" }],
"subjectType": ["Patient"],
"url": "http://testing.test",
"item": [
{
"linkId": "1.1",
"type": "choice",
"text": "Lorem ipsum dolor sit amet, consectetur adipiscing elit?",
"required": true,
"answerOption": [
{
"valueCoding": {
"code": "very-severe",
"system": "urn:uuid:b8ef0384-7163-44fa-e977-d5c64bce8cb8",
"display": "Very severe"
}
},
{
"valueCoding": {
"code": "severe",
"system": "urn:uuid:b8ef0384-7163-44fa-e977-d5c64bce8cb8",
"display": "Severe"
}
},
{
"valueCoding": {
"code": "moderate",
"system": "urn:uuid:b8ef0384-7163-44fa-e977-d5c64bce8cb8",
"display": "Moderate"
}
},
{
"valueCoding": {
"code": "mild",
"system": "urn:uuid:b8ef0384-7163-44fa-e977-d5c64bce8cb8",
"display": "Mild"
}
},
{
"valueCoding": {
"code": "none",
"system": "urn:uuid:b8ef0384-7163-44fa-e977-d5c64bce8cb8",
"display": "None"
}
}
]
},
{
"linkId": "1.2",
"type": "choice",
"required": true,
"answerOption": [
{
"valueCoding": {
"code": "yes",
"system": "urn:uuid:2ab65962-d3f0-48d4-8c27-d042bfffafc3",
"display": "Yes"
}
},
{
"valueCoding": {
"code": "no",
"system": "urn:uuid:2ab65962-d3f0-48d4-8c27-d042bfffafc3",
"display": "No"
}
}
],
"text": "Lorem ipsum dolor sit amet, consectetur adipiscing elit??",
"enableBehavior": "any",
"enableWhen": [
{
"question": "1.1",
"operator": "=",
"answerCoding": {
"system": "urn:uuid:b8ef0384-7163-44fa-e977-d5c64bce8cb8",
"code": "very-severe"
}
},
{
"question": "1.1",
"operator": "=",
"answerCoding": {
"system": "urn:uuid:b8ef0384-7163-44fa-e977-d5c64bce8cb8",
"code": "severe"
}
}
]
},
{
"linkId": "1.3",
"type": "choice",
"required": true,
"answerOption": [
{
"valueCoding": {
"code": "severe-abdominal-pain",
"system": "urn:uuid:190d3b6e-015f-415e-9325-48f7b6275108",
"display": "Severe abdominal pain"
}
},
{
"valueCoding": {
"id": "05a9c9ec-1781-479f-e302-6283a66474ef",
"code": "havent-passed-gas",
"system": "urn:uuid:190d3b6e-015f-415e-9325-48f7b6275108",
"display": "Haven't passed gas from my bottom (or ostomy)"
}
},
{
"valueCoding": {
"id": "4446b2d6-c19f-4e33-e536-f4ef3cb0aa90",
"code": "vomiting",
"system": "urn:uuid:190d3b6e-015f-415e-9325-48f7b6275108",
"display": "Vomiting"
}
}
],
"extension": [
{
"url": "http://hl7.org/fhir/StructureDefinition/questionnaire-itemControl",
"valueCodeableConcept": {
"coding": [
{
"system": "http://hl7.org/fhir/questionnaire-item-control",
"code": "check-box",
"display": "Checkbox"
}
],
"text": "Checkbox"
}
}
],
"text": "Lorem ipsum dolor sit amet, consectetur adipiscing.",
"enableWhen": [
{
"question": "1.2",
"operator": "=",
"answerCoding": {
"system": "urn:uuid:2ab65962-d3f0-48d4-8c27-d042bfffafc3",
"code": "yes"
}
}
],
"item": [
{
"extension": [
{
"url": "http://hl7.org/fhir/StructureDefinition/questionnaire-displayCategory",
"valueCodeableConcept": {
"coding": [
{
"system": "http://hl7.org/fhir/questionnaire-display-category",
"code": "instructions"
}
]
}
}
],
"linkId": "1-select-one",
"text": "Select all that apply",
"type": "display"
}
]
},
{
"linkId": "1.4.1",
"type": "dateTime",
"text": "Lorem ipsum dolor sit amet, consectetur adipiscing elit?",
"required": true,
"enableBehavior": "any"
},
{
"linkId": "1.4.2",
"type": "choice",
"required": true,
"answerOption": [
{
"valueCoding": {
"code": "very-large",
"system": "urn:uuid:190d3b6e-015f-415e-9325-48f7b6275108",
"display": "Very large"
}
},
{
"valueCoding": {
"code": "large",
"system": "urn:uuid:190d3b6e-015f-415e-9325-48f7b6275108",
"display": "Large"
}
},
{
"valueCoding": {
"code": "medium",
"system": "urn:uuid:190d3b6e-015f-415e-9325-48f7b6275108",
"display": "Medium"
}
},
{
"valueCoding": {
"code": "small",
"system": "urn:uuid:190d3b6e-015f-415e-9325-48f7b6275108",
"display": "Small"
}
},
{
"valueCoding": {
"code": "very-small",
"system": "urn:uuid:190d3b6e-015f-415e-9325-48f7b6275108",
"display": "Very small"
}
}
],
"text": "Lorem ipsum dolor sit amet, consectetur adipiscing elit?"
},
{
"linkId": "1.5",
"type": "dateTime",
"text": "Lorem ipsum dolor sit amet, consectetur adipiscing elit?",
"required": true,
"enableBehavior": "any",
"enableWhen": [
{
"question": "1.4.2",
"operator": "=",
"answerCoding": {
"system": "urn:uuid:190d3b6e-015f-415e-9325-48f7b6275108",
"code": "small"
}
},
{
"question": "1.4.2",
"operator": "=",
"answerCoding": {
"system": "urn:uuid:190d3b6e-015f-415e-9325-48f7b6275108",
"code": "very-small"
}
}
]
},
{
"linkId": "1.6",
"type": "choice",
"required": true,
"answerOption": [
{
"valueCoding": {
"code": "hard-or-lumpy",
"system": "urn:uuid:190d3b6e-015f-415e-9325-48f7b6275108",
"display": "Hard or lumpy"
}
},
{
"valueCoding": {
"code": "soft-or-unformed",
"system": "urn:uuid:190d3b6e-015f-415e-9325-48f7b6275108",
"display": "Soft or unformed"
}
},
{
"valueCoding": {
"code": "loose-or-watery",
"system": "urn:uuid:190d3b6e-015f-415e-9325-48f7b6275108",
"display": "Loose or watery"
}
},
{
"valueCoding": {
"code": "unfinished",
"system": "urn:uuid:190d3b6e-015f-415e-9325-48f7b6275108",
"display": "Unfinished"
}
},
{
"valueCoding": {
"code": "difficult-to-get-out",
"system": "urn:uuid:190d3b6e-015f-415e-9325-48f7b6275108",
"display": "Difficult to get out"
}
},
{
"valueCoding": {
"code": "painful",
"system": "urn:uuid:190d3b6e-015f-415e-9325-48f7b6275108",
"display": "Painful"
}
}
],
"text": "Lorem ipsum dolor sit amet, consectetur adipiscing elit?",
"enableBehavior": "any",
"enableWhen": [
{
"question": "1.4.2",
"operator": "=",
"answerCoding": {
"system": "urn:uuid:190d3b6e-015f-415e-9325-48f7b6275108",
"code": "very-large"
}
},
{
"question": "1.4.2",
"operator": "=",
"answerCoding": {
"system": "urn:uuid:190d3b6e-015f-415e-9325-48f7b6275108",
"code": "large"
}
},
{
"question": "1.4.2",
"operator": "=",
"answerCoding": {
"system": "urn:uuid:190d3b6e-015f-415e-9325-48f7b6275108",
"code": "medium"
}
},
{ "question": "1.5", "operator": "exists", "answerBoolean": true }
]
}
]
}
It is expected that question 1.2 will be activated whenever the 'very severe' or 'severe' option is selected.
No response
A declarative, efficient, and flexible JavaScript library for building user interfaces.
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. πππ
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google β€οΈ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.