FhirQuestionnaireWidget 1.0.16

dotnet add package FhirQuestionnaireWidget --version 1.0.16
                    
NuGet\Install-Package FhirQuestionnaireWidget -Version 1.0.16
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="FhirQuestionnaireWidget" Version="1.0.16" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="FhirQuestionnaireWidget" Version="1.0.16" />
                    
Directory.Packages.props
<PackageReference Include="FhirQuestionnaireWidget" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add FhirQuestionnaireWidget --version 1.0.16
                    
#r "nuget: FhirQuestionnaireWidget, 1.0.16"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package FhirQuestionnaireWidget@1.0.16
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=FhirQuestionnaireWidget&version=1.0.16
                    
Install as a Cake Addin
#tool nuget:?package=FhirQuestionnaireWidget&version=1.0.16
                    
Install as a Cake Tool

QuestionnaireRenderer — embeddable FHIR form widget

The right-hand runtime of the FHIR Questionnaire Builder, packaged as a self-contained, embeddable widget. Drop a FHIR R4 Questionnaire into any web page and get a live, fillable form that runs the SDC logic (enableWhen, calculatedExpression, constraints, validation) and returns a valid QuestionnaireResponse — no builder shell, no iframe, no framework.

  • In-page & multi-instance — put several forms on one page; each keeps its own answers, calculations and validation state with zero cross-talk.
  • Vanilla ES module — no React/Vue/Angular required. Works with any stack.
  • Host-driven UI — the widget has no menus; you turn features on through config and drive it through a small public API.

Table of contents


Install

Fastest: CDN (no install, no auth)

Load the widget straight from jsDelivr, pinned to a release tag — nothing to download, no npm, no token:

<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/sergeymosyakov/fhir-questionnaire-builder@widget-v1.0.3/dist/questionnaire-widget.css">
<script type="module">
  import { QuestionnaireRenderer } from 'https://cdn.jsdelivr.net/gh/sergeymosyakov/fhir-questionnaire-builder@widget-v1.0.3/dist/questionnaire-widget.js';
  // …
</script>

Or the classic global build (window.FhirQuestionnaireWidget):

<script src="https://cdn.jsdelivr.net/gh/sergeymosyakov/fhir-questionnaire-builder@widget-v1.0.3/dist/questionnaire-widget.global.js"></script>

Pin to a specific @widget-v1.0.x tag for stability; jsDelivr caches immutably.

Download the release bundle

Grab the files from the GitHub Releases page and self-host them. Each release contains:

File Use it when…
questionnaire-widget.js You use ES modules (import). Recommended.
questionnaire-widget.global.js You want a classic <script> global (window.FhirQuestionnaireWidget).
questionnaire-widget.css Always — the widget’s styles.

Verify the download with the SHA256SUMS.txt published alongside the assets.

<link rel="stylesheet" href="questionnaire-widget.css">
<script type="module">
  import { QuestionnaireRenderer } from './questionnaire-widget.js';
  // …
</script>

npm (optional, for bundler projects)

If a maintainer has published to npm, bundler users (React / Vite / webpack) can:

npm install @sergeymosyakov/questionnaire-widget
import { QuestionnaireRenderer } from '@sergeymosyakov/questionnaire-widget';
import '@sergeymosyakov/questionnaire-widget/css';

npm publishing uses Trusted Publishing (OIDC from GitHub Actions — no token/secret involved); the CDN and Release above need no install and no auth and remain the primary channels.

Or build it yourself from source:

npm install
npm run build:widget       # → dist/questionnaire-widget.{js,global.js,css}

NuGet (for .NET web apps)

For Blazor, Razor Pages, or MVC apps that want the widget's static JS/CSS assets without touching npm:

dotnet add package FhirQuestionnaireWidget

Reference it from a Razor/HTML page — the assets are served under _content/FhirQuestionnaireWidget/:

<link rel="stylesheet" href="_content/FhirQuestionnaireWidget/questionnaire-widget.css">
<script type="module">
  import { QuestionnaireRenderer } from '/_content/FhirQuestionnaireWidget/questionnaire-widget.js';
  // …
</script>

Same publishing model as npm above — NuGet Trusted Publishing (OIDC from GitHub Actions, no token/secret). It's a static-asset-only package — no C# API surface, just the built widget files.


Quick start

<link rel="stylesheet" href="questionnaire-widget.css">
<div id="form"></div>

<script type="module">
  import { QuestionnaireRenderer } from './questionnaire-widget.js';

  const questionnaire = await (await fetch('my-questionnaire.json')).json();

  const widget = new QuestionnaireRenderer(document.getElementById('form'), {
    questionnaire,
    config: { previewMode: 'patient', validation: true },
  });

  widget.on('response-changed', qr => console.log('answers now:', qr));
</script>

That renders the questionnaire as a patient-facing form with a live PASS/FAIL validation badge.


Configuration

new QuestionnaireRenderer(mountEl, { questionnaire, response?, config? })

Argument Type Description
mountEl HTMLElement The container the form is rendered into (its contents are replaced).
questionnaire object FHIR R4 Questionnaire JSON. Required.
response object Optional QuestionnaireResponse to pre-fill answers.
config object Options below. Everything is off unless you opt in.

config options

Option Type Default What it does
previewMode 'patient' \| 'preview' \| 'json' 'patient' Form view (see Preview modes).
search boolean false A search box that highlights matching rows (or JSON).
validation boolean false Live PASS / FAIL badge + dropdown of items still needing attention; clicking one scrolls to it.
explain boolean false Makes calculated values and FHIRPath/enableWhen conditions clickable to open an Explain popup showing why a value or visibility rule evaluates the way it does.
tooltips boolean false Rich hover tooltips describing each field and its FHIR mapping.
navButton boolean false A “go to builder node” arrow on each row (only meaningful when a builder is present).
viewPrefs object {} Design-view toggles: { showLinkId, showPrefix, showBadges, showHiddenItems }.
language string '' Show a translated language if the questionnaire carries translations ('' = source).
fhirBaseUrl string — FHIR base server for reference search, server-side $populate, and populate()/structureMapPopulate() below.
getAuthToken () => string \| Promise<string> — Returns a Bearer token for fhirBaseUrl requests (your host's own auth — e.g. you're already logged into the FHIR server in your own app). The widget never runs its own OAuth login popup; without this, requests go out with no Authorization header (fine for public/CORS-open test servers). Independent per instance.
corsProxy string — CORS proxy for the FHIR/terminology requests.
terminology object — This widget's own terminology server for external answerValueSet expansion: { server, corsProxy, nlmApiBase }. Independent per instance — two widgets on the same page can point to two different terminology servers. Falls back to the public HL7 server (tx.fhir.org/r4) when omitted.
readOnly boolean false Render answers without editable controls.
onProgress (msg\|null) => void — Called with a message while long operations run, null when done.

Public API

widget.getResponse();          // → current answers as a FHIR QuestionnaireResponse
widget.setResponse(qr);        // load answers from a QuestionnaireResponse
widget.setLanguage('es');      // switch active language ('' = source)
widget.setConfig({ language: 'es' });    // runtime config — only `language` takes effect
widget.populate('Patient/123');            // SDC $populate against config.fhirBaseUrl
widget.structureMapPopulate('Patient/123'); // run the Questionnaire's sourceStructureMap against a fetched resource
widget.on(event, cb);          // subscribe (returns the widget)
widget.off(event, cb);         // unsubscribe
widget.destroy();              // remove the widget and free all listeners

populate()/structureMapPopulate() merge the resulting answers in place and emit info on success or error on failure (see Events) — nothing is shown on the page unless you subscribe.

getResponse() always returns a fresh, valid FHIR R4 QuestionnaireResponse built from the current answers — this is your integration point for saving, submitting, or exporting.

Note: the chrome flags (search, validation, explain, tooltips, navButton) are construction-time — set them in the initial config. setConfig() only applies language at runtime; to change chrome, destroy() and create a new instance.


Events

Subscribe with widget.on(name, cb):

Event Payload Fires when
ready — The widget has mounted and rendered the first time.
response-changed QuestionnaireResponse Any answer changes.
language-changed string (lang) The active language changes.
render — The form re-renders.
info string populate()/structureMapPopulate() succeeded.
error string populate()/structureMapPopulate() failed (e.g. fhirBaseUrl not set) — nothing is shown unless you listen.

Example: custom “Export FHIR R4” button

The widget deliberately ships no toolbar. To let a user export their answers, add your own button on the host page and call getResponse() — the returned object is a ready-to-save FHIR R4 QuestionnaireResponse:

<div id="form"></div>
<button id="export">Export FHIR R4</button>

<script type="module">
  import { QuestionnaireRenderer } from './questionnaire-widget.js';

  const questionnaire = await (await fetch('my-questionnaire.json')).json();
  const widget = new QuestionnaireRenderer(document.getElementById('form'), {
    questionnaire,
    config: { previewMode: 'patient', validation: true },
  });

  document.getElementById('export').addEventListener('click', () => {
    const qr = widget.getResponse();               // ← ask the widget for answers
    const blob = new Blob([JSON.stringify(qr, null, 2)], { type: 'application/fhir+json' });
    const url = URL.createObjectURL(blob);
    const a = Object.assign(document.createElement('a'), {
      href: url, download: 'questionnaire-response.json',
    });
    a.click();
    URL.revokeObjectURL(url);
  });
</script>

A working version of this button is in the live demo.


Preview modes

config.previewMode picks how the form looks:

  • patient — the clean, fillable form a respondent sees.
  • preview — the design view with link IDs, prefixes and status badges.
  • json — the live QuestionnaireResponse / Questionnaire JSON.

Multiple isolated widgets

Each widget runs on its own event channel and its own answer store, so two forms on the same page never affect each other:

const a = new QuestionnaireRenderer(elA, { questionnaire: qA });
const b = new QuestionnaireRenderer(elB, { questionnaire: qB });
// answering a never touches b

See the live demo for a three-widget page (one per preview mode) over the same questionnaire.


Styling

Link questionnaire-widget.css once. It carries the widget’s design tokens and all preview/control/modal styles, scoped so they don’t leak into your page’s layout (no global body/reset rules). Override the CSS custom properties on a wrapping element to re-theme (e.g. --c-primary, --c-border, --c-surface).


Browser support & dependencies

  • Modern evergreen browsers (ES2020 modules).
  • The ESM/global bundles include their runtime dependencies (FHIRPath, DOMPurify, marked) — no extra <script> tags needed.
  • No network calls unless you set fhirBaseUrl (reference search / $populate) or use terminology expansion.
Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • .NETStandard 2.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.16 90 9/23/2026
1.0.15 112 9/3/2026
1.0.14 105 9/2/2026
1.0.13 106 8/26/2026
1.0.12 109 8/23/2026