This log documents changes for the @aehrc/smart-forms-renderer. This project follows Semantic Versioning.
For changelogs of other libraries, please refer to their respective repositories under the /packages folder:
- SDC-Populate: /packages/sdc-populate/CHANGELOG.md
- SDC-Assemble: /packages/sdc-assemble/CHANGELOG.md
- SDC-Template-Extract: /packages/sdc-template-extract/CHANGELOG.md
Changelog only includes changes from version 0.36.0 onwards.
- Added a headless engine entrypoint, published as
@aehrc/smart-forms-renderer/engine, that re-exports the SDC engine - form lifecycle,QuestionnaireResponseconstruction/traversal, item inspection, answer parsing, repopulation and observation-based extraction - without pulling in Material UI, Emotion,react-domor other DOM/UI dependencies. Anexportsmap is now published covering every path the package previously exposed only via internallib/...deep imports. - Added i18n support for renderer-owned UI text ("chrome") and locale-aware, order-aware date formatting/validation (e.g. year-first locales correctly get
YYYY/MM), configured via the existingrendererConfigStore'slocaleandrendererStringsoptions. Consuming apps supply their own translation catalogs; defaults remain unchanged (English, DD/MM/YYYY), so existing consumers are unaffected. - Styled warning-level validation feedback (from
targetConstraintviolations andOperationOutcomeissues) differently from errors - amber helper text with no red border - and exporteduseValidationFeedbackSeverityso consumers can act on feedback severity directly.useValidationFeedbackis kept as a deprecated wrapper. See issue #1984
- Fixed answerOption-based choice fields (Select, Autocomplete, Radio, Checkbox) showing raw codes, becoming unresponsive, or desyncing from the stored answer when a terminology
$lookupfails or an option's display text changes. Options whose display cannot be resolved are now filtered out of the list with a single warning shown below the field, since raw codes are not acceptable in a clinician-facing UI, while a previously-answered option is preserved using its live or originally-recorded display instead of vanishing. Several related falsy-value (0,'') and key-collision matching bugs are also fixed. See issue #1931 - Fixed autocomplete choice fields showing "No options" while a terminology search is still below the debounce threshold, instead of a "Type to search..." prompt.
- Fixed repeating group validation errors displaying on every instance instead of only the invalid one - errors are now scoped by the instance's position within the
QuestionnaireResponse, including when that position differs from the rendered row position (e.g. after agtablerow is deselected). - Fixed clearing an autocomplete/choice field leaving a stale answer in the
QuestionnaireResponseinstead of removing it, and fixed repeat group instances/gtablerows not being removed when clearing their last answer left them empty. - Fixed wrapped, multi-line question labels rendering below their field instead of beside it.
- Instruction text (
displayitems withquestionnaire-displayCategory: instructions) is now programmatically associated with its parent input field viaaria-describedbyacross all field types. Screen readers now announce the instruction text when the field receives focus, rather than requiring a separate tab to the instruction item. See issue #1640 - Added rendering of
Questionnaire.titleanditem.prefix. Both now appear in the renderer, and support text styling viarendering-style,rendering-markdown, andrendering-xhtmlextensions. SethideQuestionnaireTitle: truein the renderer config to suppress the built-in title rendering. - Added
responseHasErrorsto theQuestionnaireResponseStore. This istruewhen the response contains items with error or fatal severity — it does not consider warnings. - Added item-level
targetConstraintsupport. Constraints can now be defined directly on questionnaire items (not only at the questionnaire root), and are extracted and evaluated per-item. - Added screen reader announcements for error messages in input fields via
role='alert'andaria-live='assertive'. See issue #1745 - Improved responsive layout on large screens — the renderer now expands to fill available screen width, with per-item max-widths applied to keep individual inputs at a readable size. See issue #1936
- Added horizontal dividers between repeat group instances in
RepeatGroupView. - The remove button in repeat groups is now enabled even when only one instance remains, allowing users to clear pre-populated data. Removing the last instance leaves one blank instance in its place. See issue #1810
- Fixed
targetConstraintexpression logic being inverted — per the FHIR spec, expressions should returntruewhen the constraint is satisfied (valid). See issue #1954 - Fixed validation errors (required,
targetConstraint) not surfacing ondateanddateTimefields. These fields now correctly report constraint and required errors. - Fixed
dateanddateTimefields not validating againstminValue/maxValueconstraints. - Fixed repopulate dialog incorrectly showing unchanged repeat group items as modified after a user had deleted or reordered instances. The comparison was positional, so any shift in item index caused remaining items to appear as changed. Matching is now content-based. See issue #1940
- Fixed
getResponse()andremoveEmptyAnswers()strippingitem.definitionfrom returned QuestionnaireResponse items. See issue #1801 - Fixed selected value in choice select (autocomplete) fields appearing too far left due to missing padding. See issue #1842
- Fixed deeply nested repeat group content being pushed off-screen when zooming in, with no scrollbar to access it. Group items now scroll horizontally independently. See issue #1809
- Fixed validation feedback text not wrapping correctly in grid/table cells for autocomplete-based choice fields — it was rendered as a flex sibling of the input, compressing it into the remaining row space. Feedback now stacks below the input. Also fixes the missing error border on these fields when feedback is present.
- Fixed accordion scroll position jumping when expanding accordion items. See issue #1796
- Fixed the sticky tab list overflowing the viewport on long forms. The tab list now dynamically constrains its height and becomes scrollable when needed.
- Added
tabListStickyTopoption to the renderer store. When supplied, a tabbed form's tab menu will stick to the top of the page offset by this value, keeping it visible during scrolling. fhirContextreferences from SMART App Launch are now resolved and stored in the renderer SMART config, making them available for use inanswerExpressions.
- Conditionally display placeholder in select fields, fixing issue 1834
- Reduced vertical padding and margins to limit excessive whitespace in the renderer.
- Changed standalone autocomplete fields to be multiline so that value is not truncated.
- Fixed regression causing some calculatedExpressions to not be displayed.
- Fixed an issue where existing QuestionnaireResponse repeat group items were being overwritten by blank data when applying calculatedExpression values, causing issue #1811
- Added support for text styling on answerOption.valueString.
- Improved keyboard-only navigation and screen reader accessibility for combobox dropdowns. See issue #1762
- Fixed missing calculatedExpression sync animations on
choiceandopen-choiceitems. See issue #1643 - Fixed regression in enableWhen initialisation that prevented some items from populating. See issues #1781 and #1775
- Fixed an issue where enableWhen items are not initialising when a filled form is passed into
buildForm().
Use 1.2.10 instead of 1.2.9 due to a publishing issue.
- Add aria-hidden="true" to text-field based questions' clear button (x).
- Add aria-hidden="true" to text-field based questions' clear button (x).
- Required field asterisks accessibility enhancements also applies to group headings and tab buttons.
- Required field asterisks are now properly announced as "Mandatory field" by screen readers. Refer to issue #1741
- Remove
openOnFocusprop from autocomplete fields to allow screen readers to read out label, placeholder text and control's role. Refer to issue #1733
- Use
deepEqualfor checkbox answer matching instead of JSON.stringify equality to correctly compare valueCoding objects. Refer to issue #1738
- Measurement units (e.g. cm, kg) are now associated with their input fields, ensuring screen readers correctly announce the unit when the field receives focus. Refer to issue #1641
- Fixed bug with the rendering of the calculation animation on the first calculated expression update. Issue described here
- Fixed bugs with the rendering and updating of nested items, within an item that is a repeat item. The issue is described here
- Fixed valueSet promise resolution in buildForm stage to exclude answerValueSet urls from autocomplete items. This is because these urls are meant to be used alongside a
filterparameter. - Fixed renderer calcExp not working on open-choice and choice fields. Issue is described here
- Fixed renderer open-choice not retaining the selected option in calcExp. Issue is described here
- Changed renderer aria-label as per request described here
- Added support for optional heading focus when switching tabs via
disableHeadingFocusOnTabSwitchfield inRendererConfigStore.
- Added calcExpUpdated prop to overrideComponent interface.
- Fixed accurate option highlighting in
choiceautocomplete items.
(WARNING: Major breaking changes with library API)
For smooth migration, a migration guide is provided at MIGRATION-v1.0.md.
buildForm()anduseBuildForm()now accept aBuildFormParamsobject instead of multiple parameters.- The
additionalVariablesparameter is replaced withadditionalContext. Its usage remains the same - it is used to inject additional fhirPathContext variables. - A new library function
repopulateForm()is added to repopulate the form with a new QuestionnaireResponse and/or additionalContext while preserving the current Questionnaire state. Its parameters are defined in the interfaceRepopulateFormParams.
-
If you were previously calling
QuestionnaireStore.setPopulatedContextto inject populatedContext into the renderer, you no longer need to do so.buildForm(),useBuildForm()andrepopulateForm()will take care of it for you via theadditionalContextparameter. -
For pre-population/re-population, you do not need to call
QuestionnaireStore.updatePopulatedPropertiesandQuestionnaireResponseStore.setUpdatableResponseAsPopulatedanymore. Both of these functions are now removed.buildForm(),useBuildForm()andrepopulateForm()will take care of it for you.- // Remove these lines - const updatedResponse = await updatePopulatedProperties(populatedResponse, populatedContext); - setUpdatableResponseAsPopulated(updatedResponse); - - if (populatedContext) { - setPopulatedContext(populatedContext, true); - } + // Re-run buildForm (or repopulateForm) with the new populatedResponse + await buildForm({ + questionnaire: sourceQuestionnaire, + questionnaireResponse: populatedResponse, + terminologyServerUrl: defaultTerminologyServerUrl, + additionalContext: populatedContext + }); -
QuestionnaireStore.populatedContextandQuestionnaireStore.setPopulatedContextare replaced withQuestionnaireStore.additionalContextandQuestionnaireStore.setAdditionalContextrespectively. You most likely won't need to callsetAdditionalContextmanually. -
It is still recommended to create your own wrapper function that calls
destroyForm()to clean up states when the form is unmounted before callingbuildForm()again.async function resetAndBuildForm(params: BuildFormParams) { // Destroy previous questionnaire state before building a new one destroyForm(); // Build new questionnaire state await buildForm(params); }
RendererStylingStoreand interfaceRendererStylingare replaced withRendererConfigStoreandRendererConfigrespectively. This is purely a naming change.rendererConfigOptionscan now be passed into the renderer viabuildForm()anduseBuildForm(). You no longer need to callsetRendererConfigStoremanually.
useStringCalculatedExpressionanduseCodingCalculatedExpressionhooks are removed. CalculatedExpressions are now triggered via an internal task queue. If you are using these hooks in a component override, you can remove the hook safely.objectIsCodinglibrary function is removed.
- Take questionnaire-unit into account when updating QR via Quantity item calculatedExpressions.
- Fixed an issue where radio buttons and checkboxes are unreadable on mobile viewports.
- Added preferredTerminologyServer compatibility with valueUri.
- Increased renderer's tolerance when working with valueCoding without codes.
- Update dependencies to fix incompatible Node and dependency versions.
- Bump version to set NPM tag to latest.
- Fixed an issue where inputs in checkbox open-choice's open label field does not update the QuestionnaireResponse.
- Fixed unexpected behaviour of open-choice's open label field clearing the answers of previously selected options.
- Fixed an issue where enableWhen logic was not working properly with repeating items.
- Added support for the preferredTerminologyServer SDC extension.
- Completely removed persisting "iframe-resizer" dependencies as a follow-up to v0.43.0.
- Removed external dependency on "iframe-resizer" while retaining dynamically sized Storybook iframes in the documentation.
- Replaced all instances of cloneDeep() with the native structuredClone() function.
- Changed Storybook iframes in the documentation to be dynamically sized based on the content.
- Significantly improved performance by reducing the number of re-renders.
- Adjusted renderer's background color to be #fafafa.
- Removed left and right paddings from the renderer - it now takes up the full width of its container.
- Fixed inconsistencies when syncing the renderer's internal state with externally-generated QuestionnaireResponses.
- Fixed inconsistencies with internal IDs for tracking repeating items and groups.
- Fixed an issue where the renderer's theme was overriding the parent app's styles.
- Fixed issues with lodash dependencies in package.json.
- Added a library function removeInternalIdsFromResponse() to remove internal IDs for tracking repeating items.
- Fix date validation error message for two matches.
- Fix generation of internal IDs for repeat items and groups to be consistent and sync-able with externally-generated QuestionnaireResponses.
- Added a simple, minimal fix to dynamically adjust field positions based on viewport
- Added support for Observation-based extraction as a library function and as a feature in the Playground.
- Refactored
repeatitems so that it tracks item instances using the QuestionnaireResponse, instead of using React'suseState.
- Fixed an issue where
stringandtextitems were automatically removing inputted trailing whitespaces.
- Fixed support for item.initial and item.answerOption.initialSelected for repeating groups.
- Added support for non-repeating group table (
gtable) items.
- Added support for
Quantityitems. See documentation and Storybook for more details.
- Fixed a @aehrc/sdc-populate library dependency issue.
- Added support for
pageUI Control code from https://hl7.org/fhir/extensions/ValueSet-questionnaire-item-control.html.
- Add support for
Codingtype in calculatedExpressions for choice and open-choice items.
- Add Save-Extract-Write functionality (StructureMap-based) in the "Save as Final" button in the Smart Forms app.