LHC-Forms
A widget for rendering feature-rich forms defined in JSON definition files
What is LHC-Forms?
LHC-Forms (a.k.a.
LForms) is a feature-rich, open-source widget that creates input forms based on definition
files for Web-based applications. The definition files are typically in a format
known as HL7® FHIR®
Questionnaires,
but can also be in LHC-Forms' internal format. LHC-Forms was developed by the Lister Hill National
Center for Biomedical
Communications (LHNCBC), National Library of
Medicine (NLM), part of the National Institutes of
Health (NIH), with the collaboration and support from the
Regenstrief Institute, Inc. and the
LOINC Committee.
Features
See the demos for a step-by-step introduction.
Features include:
- Form definitions are defined in JSON, listing the questions
- Sections containing questions
- Repeating sections and questions (by specifying cardinality)
- Hiding and showing questions via skip logic based on the user's answers to
other questions
- Scores for answers which update a total score field.
- Coded answer lists which might require a matching input
- Default values
- Unit lists for numeric questions
- Date fields
- Help messages for questions
- Support for HL7 FHIR Questionnaires
For a more detail on support for FHIR Questionnaires, and the associated
Structured Data Capture (SDC)
Implementation Guide, see the documentation for FHIR version R4
support, FHIR version
R5 support, and SDC
support.
Installation
LHC-Forms can be used either as a prebuilt package or installed using
npm (npm
install lforms
), but see the note below about the
npm installation). If you aren't using npm, the simplest way to start using
LHC-Forms is by linking to the prebuilt version hosted on
lhcforms-static.nlm.nih.gov. The URLs for the CSS and JavaScript are:
- CSS
- https://lhcforms-static.nlm.nih.gov/lforms-versions/36.3.2/webcomponent/styles.css
- JavaScript
-
- https://lhcforms-static.nlm.nih.gov/lforms-versions/36.3.2/webcomponent/assets/lib/zone.min.js
- https://lhcforms-static.nlm.nih.gov/lforms-versions/36.3.2/webcomponent/lhc-forms.js
The zone.min.js file should be left out if you already have that in your
page (e.g. if the page contains an Angular app).
- JavaScript for FHIR Support (recommended)
- Additionally, you will probably want ONE of the following files for FHIR
support. The first file provides support for the STU3, R4, and R5 versions of FHIR,
and the others provide support for one specific version.
- https://lhcforms-static.nlm.nih.gov/lforms-versions/36.3.2/fhir/lformsFHIRAll.min.js
- OR https://lhcforms-static.nlm.nih.gov/lforms-versions/36.3.2/fhir/R5/lformsFHIR.min.js
- OR https://lhcforms-static.nlm.nih.gov/lforms-versions/36.3.2/fhir/R4/lformsFHIR.min.js
- OR https://lhcforms-static.nlm.nih.gov/lforms-versions/36.3.2/fhir/STU3/lformsFHIR.min.js
Note that the URLs contain a release version number, 36.3.2, for which you
can substitute any of the other prebuilt versions (36.3.2 or higher) available at
https://lhcforms-static.nlm.nih.gov/lforms-versions.
For production applications, if you would prefer to download these files
and serve them from your server to avoid introducing a dependency on the
lhcforms-static servers, zip files of each version's files are available at
https://lhcforms-static.nlm.nih.gov/lforms-versions.
If you decide to use the npm package, note that for now the JavaScript files
do not work when the package is required or imported, so you will still need to
load the above files from the npm package's directory via script tags. We are hoping to find a solution that
will allow them to be imported in the future.
You might also find the lforms-loader npm package to
be helpful. It can load a specified version of LHC-Forms onto your webpage by
adding the needed link and script tags.
Usage
Rendering a Form
In your HTML, create an element to hold the form. You will pass a
reference to this element or its ID to a utility function load the form.
HTML
<div id="myFormContainer"></div>
Also include the above JavaScript and CSS files on the page.
JavaScript
LForms.Util.addFormToPage(formDefinition, 'myFormContainer', options);
Parameters:
- formDefinition - a FHIR Questionnaire, or form definition in LHC-Forms'
internal format (either JSON or
a parsed object)
- formContainer - an element (or its ID, as in this example) into which the
form should be placed
- options - A map of options, which can be:
- prepopulate
- Set this to true if you are using FHIR and want prepopulation
to occur from the patient's record. Note that you probably do not want prepopulation to
happen if you are loading a QuestionnaireResponse (via the
questionnaireResponse option).
- fhirVersion
- If the formDefinition is a FHIR Questionnaire,
you can specify which version of FHIR by passing in 'STU3', 'R4', or 'R5'.
Otherwise LForms will try to guess the version by looking at the Questionnaire's
structure.
- questionnaireResponse
- A FHIR QuestionnaireResponse which
should be loaded into the rendered form.
Returns: a promise that will resolve after all external FHIR resources needed
by the Questionnaire (see setFHIRContext below) have been loaded (at which point the form
should be visible).
Setting a FHIR Source
If the Questionnaire does prepopulation of form fields with data, or if it
loads ValueSets but does not specify a terminology server, then the following API
will need to be called prior to addFormToPage. It provides a connection to a FHIR
server and/or some FHIR resources to use in prepopulation.
LForms.Util.setFHIRContext(fhirContext, fhirContextVars)
Parameters:
- fhirContext - (optional) an instance of 'client-js', a.k.a. the npm package fhirclient, version 2.
(See http://docs.smarthealthit.org/client-js
for documentation. A non-npm version, ready to use in a browser, can be found
at https://cdn.jsdelivr.net/npm/fhirclient@2/build/fhir-client.min.js.) It
should be initialized with a connection to the FHIR server to be used. As an example, one common
need for this parameter is to set not only the FHIR server but also the
patient ID. There is an undocumented feature of the fhirclient library
that lets you do that this way:
LForms.Util.setFHIRContext(FHIR.client({serverUrl: serverUrl, tokenResponse: { patient: patientId }}));
However, if all that is needed from the FHIR server by the Questionnaire
are resources for launchContext variables, this parameter can be omitted if the next
parameter is provided.
- fhirContextVars - (optional) data for the FHIR launchContext
extension which makes variables available to other expressions in a Questionnaire. If
provided, fhirContextVars should be a map from variable names declared in the launchContext
extensions to FHIR resources (as objects). For example, {'someVarName', someValue}.
The fhirContext can also be used to supply this data for certain standard
variables like "patient" and "encounter", but it will only be used for
those values if not supplied here.
Retrieving User-Entered Data
After a user has filled out the form the user-entered data can be
retrieved as FHIR QuestionnaireResponse
resource, using the following utility method, which also supports getting
the Questionnaire back (a feature useful for converting between FHIR versions):
LForms.Util.getFormFHIRData(resourceType, fhirVersion, formDataSource, options)
Parameters:
- resourceType - a FHIR resource type, which should be one of
"QuestionnaireResponse", "Questionnaire", "DiagnosticReport".
- fhirVersion - the version of FHIR being used. This can be set to either
"STU3", "R4", or "R5".
- formDataSource - (optional) either the containing HTML element that
includes the rendered form, a CSS selector for that element, an
LFormsData object (such as returned by LForms.Util.getFormData), or an
LHC-Forms form definition (parsed). If not provided, the first LHC-Forms
form found in the page will be used.
- options - an optional hash of other options, with the following optional keys:
- extract - a flag (true or false, false being the default)
used for resourceType=QuestionnaireResponse to indicate that data should
be extracted
(using the FHIR observationExtract extension) to other FHIR resources.
In this case the return value will be an array consisting of the
QuestionnaireResponse and any extracted Observations.
- subject - a local FHIR resource that is the subject of the output
resource. If provided, a reference to this resource
will be added to the output FHIR resource when applicable.
- bundleType - optional, and only used for DiagnosticReport output.
This may be either "transaction" or "collection", and requests
that the DiagnosticReport and associated Observation resources be placed
together in a bundle of that type. When this is not present, a bundle
will not be used.
Form Validation
Prior to submitting the form, the form can be checked to make sure required fields are filled
in and that the values have the correct format, by using the following function:
LForms.Util.checkValidity(formElement)
An array of errors will be returned if the form is invalid. If the form is
valid this function returns null.
Parameters:
- formElement - (optional) an HTML element that includes the rendered form. If
this is omitted, the "body" tag will be used. If there is more than one
LHC-Forms form within formElement, the first found will be used.
Other APIs
The following are older APIs which might still be useful in some
situations.
Importing a FHIR Questionnaire Resource into the LHC-Forms Format
A FHIR Questionnaire resource can be converted/imported into the LHC-Forms format,
which can then be loaded into the LHC-Forms widget to show the form. To do
that conversion, LHC-Forms provides the following
utility method. Note also that the addFormToPage method documented above
can take a FHIR Questionnaire, so this API should seldom be needed.
LForms.Util.convertFHIRQuestionnaireToLForms(fhirData, fhirVersion)
Parameters:
- fhirData - a FHIR Questionnaire resource (parsed). If you run into a problem,
please open an issue on the LForms repository.
- fhirVersion - the version of FHIR in which the Questionnaire is
written (currently takes either "STU3" or "R4"). This maybe be omitted if
the Questionnaire resource (in fhirData) contains a meta.profile
attribute specifying the FHIR version. If both are provided, this takes
precedence.
Returns: a form definition in the LHC-Forms format.
Importing a FHIR QuestionnaireResponse into an LHC-Forms Form
FHIR QuestionnaireResponses (and also a DSTU2 version of DiagnosticReports,
if generated by LHC-Forms) can be loaded into an LHC-Forms form definition to
produce a structure that can be loaded into the LHC-Forms widget (using addFormToPage) To merge FHIR resources into LHC-Forms data,
LHC-Forms provides the following utility method:
LForms.Util.mergeFHIRDataIntoLForms(resourceType, fhirData, formData, fhirVersion)
Parameters:
- resourceType - a FHIR resource type. Currently only
"QuestionnaireResponse" and "DiagnosticReport" (either a
DiagnosticReport resource with "contained" Observation resources or a
"searchset" typed Bundle of a DiagnosticReport and associated Observation
resources) are supported.
- fhirData - a FHIR resource of the type specified in the resourceType
parameter. Note that for DiagnosticReports, the merge will only
work if the DiagnosticReport was originally generated by LHC-Forms.
- formData - an LHC-Forms form definition or data object. This can be
obtained by converting a FHIR Questionnaire.
- fhirVersion - the version of FHIR in which the resource is
written (currently takes either "STU3" or "R4"). This maybe be omitted if
the resource (in fhirData) contains a meta.profile
attribute specifying the FHIR version. If both are provided, this takes
precedence.
Returns: a form definition object but with the user data merged
into it. It can be displayed using LForms.Util.addFormToPage as described above.
Retrieving User-Entered Data as HL7 V2 OBR and OBX segments
The user entered data, along with some form definition data can be retrieved as HL7 V2 OBR and OBX segments.
To retrieve that data, LHC-Forms provides the following utility method:
LForms.Util.getFormHL7Data(element)
Parameters:
- element - (optional if there is only one LHC-Forms widget on the page.) The containing HTML element that includes
the LHC-Forms rendered form. It could be the DOM element or its id.
Returns: a string of HL7 V2 data
Getting the Internal Format Form Definition Combined with the User Data
LForms.Util.getFormData(formElement, noEmptyValue, noDisabledItem)
The utility method LForms.Util.getFormData()
will return both the user
data and the complete form definition data together in a way that can be fed back to LHC-Forms
to display the form with the data. This is useful when you want to allow the
user to save the form so it can be redisplayed later for completion or editing
(and if for some reason you are not using FHIR).
Parameters:
- formElement - an HTML element that includes the rendered form. If
this is omitted, the "body" tag will be used. If there is more than one
LHC-Forms form within formElement, the first found will be used.
- noEmptyValue - (default false) Remove items that have an empty value
- noDisabledItem - (default false) Remove items that are disabled by skip
logic
Returns: a form definition object but with the user data merged
into it. It can be displayed using LForms.Util.addFormToPage as described above.
Retrieving Only the User-Entered Values
LForms.Util.getUserData(formElement, noFormDefData, noEmptyValue, noHiddenItem)
Parameters:
- formElement - an HTML element that includes the rendered form. If
this is omitted, the "body" tag will be used. If there is more than one
LHC-Forms form within formElement, the first found will be used.
- noFormDefData - (default false) If this is true, the form
definition data will not be returned along with the data, except for item codes.
Even when false, the form definition data included is only the item-level data,
not the form-level data.
- noEmptyValue - (default false) If this is true, items that have
an empty value will be removed.
- noHiddenItem - (default false) If this is true, items that are
hidden by skip logic will be removed.
To get a compact structure with just the user-entered data and minimal form
definition data, you can call LForms.Util.getUserData(formElement, true, true,
true)
.
Form Definition Format
Form definitions are stored in a JSON structure, which is either FHIR
Questionnaire
(recommended) or the LHC-Forms internal format. To get a rough idea of what
the internal format is you can take a look at one of the
samples,
or see the
form definition documentation.
Licensing and Copyright Notice
See the LICENSE.md file in the lforms package on GitHub.
Issues & Announcements
For reporting problems with LHC-Forms, please open an issue on
GitHub.
Note that the team developing LHC-Forms also works on several others packages,
so we might not be able to respond as quickly as we would like.
To receive occasional announcements about
changes or updates to LHC-Forms, sign up for the email list by sending the
message "subscribe LHCFORMS-ANNOUNCE" (no subject needed) to listserv@list.nih.gov.
These announcements will probably just be about significant changes.
Project maintained by LHNCBC.
Hosted on GitHub Pages — Based on theme by mattgraham