fhir_renderer_questionnaire 1.0.0
fhir_renderer_questionnaire: ^1.0.0 copied to clipboard
A flutter package to render FHIR questionnaires, based on the FHIR R4 specification.
FHIR Renderer Questionnaire #
A Flutter package for FHIR® R4 Questionnaires. HL7®, and FHIR® are the registered trademarks of Health Level Seven International and their use of these trademarks does not constitute an endorsement by HL7.
This package was inspired by fhir_questionnaire. Built to allow isolated customization and different ways to render a FHIR R4 Questionnaire.
🔆 Why fhir_renderer_questionnaire? #
- 🎨 Customization — Replace the default Questionnaire Item widgets with your own to achieve the desired UI.
- 🤸 Flexibility — Use the RendererView that suits you the best (ListViewRenderer, PageViewRenderer, SliversViewRenderer).
- 🚀 Rapid Development: Automatically generates UI from FHIR R4 Questionnaires, saving time compared to building forms manually.
- 📝 Automatic QuestionnaireResponse Generation: Collects user input and produces a valid
QuestionnaireResponse. - ⚙️ Behavior Handling: Manages conditional logic (
enableWhenandrequired) out of the box.
🔆 Widgets #
✳️ In order to provide full customization, not only for the QuestionnaireItems but also the Questionnaire itself, there are three rendering options to suit specific UI needs: QuestionnaireListViewRenderer, QuestionnairePageViewRenderer and QuestionnaireSliversViewRenderer.
✳️ The three rendering options use by default the theme of your application.
💫 QuestionnaireListViewRenderer #
💡 Ideal for long questionnaires as it uses ListView.builder under the hook.
QuestionnaireListViewRenderer(
rendererController: RendererQuestionnaireController(questionnaire: example),
),
💫 QuestionnairePageViewRenderer #
💡 Ideal for strict grouping in the questionnaires as gives the user a clear separation of the QuestionnaireItems.
QuestionnairePageViewRenderer(
rendererController: RendererQuestionnaireController(questionnaire: example),
);
💫 QuestionnaireSliversViewRenderer #
💡 Ideal for fancy behaviors through your questionnaire.
QuestionnaireSliversViewRenderer(
rendererController: RendererQuestionnaireController(questionnaire: example),
);
❗❗ The builders of the
QuestionnaireSliversViewRendererexpect you to return aWidgetof typeSliver.
🔆 Core Capabilities #
- Validation Support: Custom regex validation via FHIR extensions plus automatic default validation for integer, decimal, url, and quantity types
- Smart Keyboard Types: Automatically selects appropriate keyboard (number pad for integers, decimal pad for decimals, URL keyboard for URLs, multiline for text)
- Conditional Logic: Full support for
enableWhenwith AND/OR behavior to show/hide items based on user responses - Read-Only Mode: Force the entire questionnaire into read-only mode using
forceReadOnlyView - Initial Values: Pre-populate questionnaires with existing data using
initialQuestionnaireResponse - Item Control Extensions: Support for dropdown, radio-button, and checkbox rendering via FHIR
questionnaire-itemControlextension - Custom Builders: Replace any default widget with your own implementation for complete UI control
- Performance Optimized: EnableWhen caching system and optimized rendering for large questionnaires
- Memory Management: Proper cleanup of resources (FocusNode, TextEditingController) to prevent memory leaks
🔆 Usage #
✳️ The QuestionnaireListViewRenderer, QuestionnairePageViewRenderer and QuestionnaireSliversViewRenderer allow you to customize each QuestionnaireItem widget by using builders.
Each builder receives:
index, to know its own position within the group or set of items.isLastItem, a boolean to allow last-item customization.questionnaireItem, the questionnaire item to display.
The builders for the questionnaire items that allow a user answer receive also:
selectedResponse, the selected questionnaire response item.onAnswerChanged/onAnswerOptionSelected, to notify when the answer changes.
The following example uses the choiceItemBuilder to replace the default UI of the choice item type for a custom one:
import 'package:example/widgets/segmented_choice.dart';
import 'package:fhir_r4/fhir_r4.dart';
import 'package:fhir_renderer_questionnaire/fhir_renderer_questionnaire.dart';
import 'package:flutter/material.dart';
//Cubit or Bloc or Controller for the view to assign
//the QuestionnaireRendererController instance.
class CubitOrBlocOrController {
QuestionnaireRendererController? rendererController;
}
class ListViewExamplePage extends StatelessWidget {
final Questionnaire questionnaire;
ListViewExamplePage({super.key, required this.questionnaire});
final CubitOrBlocOrController controller = CubitOrBlocOrController();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("QuestionnaireListViewRenderer"),
actions: [
IconButton(
onPressed: () {
final generatedQuestionnaireResponse =
controller.rendererController
?.getGeneratedQuestionnaireResponse();
//Do something with the generated response
},
icon: Icon(Icons.check),
),
],
),
body: QuestionnaireListViewRenderer(
questionnaire: questionnaire,
getRendererControllerInstance:
(QuestionnaireRendererController controller) =>
this.controller.rendererController = controller,
choiceItemBuilder: (
index,
isLastItem,
selectedResponse,
questionnaireItem,
onAnswerOptionSelected,
) {
return Padding(
padding: const EdgeInsets.all(10.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"${questionnaireItem.text}",
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16),
),
SegmentedChoice<QuestionnaireAnswerOption>(
selectedValue:
questionnaireItem.answerOption
?.where(
(item) =>
item.valueCoding ==
selectedResponse
?.answer
?.firstOrNull
?.valueCoding,
)
.firstOrNull,
values: questionnaireItem.answerOption!,
valueNameResolver:
(value) => "${value.valueCoding?.display?.valueString}",
enabled: true,
onSelectedValueChanged: (value) {
onAnswerOptionSelected(value);
},
),
],
),
);
},
),
);
}
}
Using choiceItemBuilder:
🔆 Supported Questionnaire Items #
fhir_renderer_questionnaire supports the following Questionnaire Item types from FHIR R4:
group- Container for nested itemsdisplay- Instructional/display textboolean- Yes/No questionsdecimal- Decimal numbersinteger- Whole numbersdate- Date pickerdateTime- Date and time pickertime- Time pickerstring- Short text inputtext- Multi-line text inputurl- URL inputchoice- Single selection from optionsopen-choice- Choice with free-text optionquantity- Numeric value with unitsattachment- File upload (images, PDFs, documents) ✨ NEWreference- Reference to FHIR resources (Practitioner, Patient, etc.) ✨ NEW
16 of 17 FHIR R4 types implemented (94% coverage)
Missing: question (deprecated generic type, rarely used)
✳️ Use the example project ✳️
🔆 📣 🔜 Roadmap #
🔳 Support for localization extensions 🔳 Complete unit tests 🔳 Widget tests
❗❗ The roadmap above was created out of specific needs. If you have ideas for features or important functionality to support, please create an issue with your suggestion.