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:

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
  1. https://lhcforms-static.nlm.nih.gov/lforms-versions/36.3.2/webcomponent/assets/lib/zone.min.js
  2. 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:
  1. formDefinition - a FHIR Questionnaire, or form definition in LHC-Forms' internal format (either JSON or a parsed object)
  2. formContainer - an element (or its ID, as in this example) into which the form should be placed
  3. 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:
  1. 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.
  2. 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:
  1. resourceType - a FHIR resource type, which should be one of "QuestionnaireResponse", "Questionnaire", "DiagnosticReport".
  2. fhirVersion - the version of FHIR being used. This can be set to either "STU3", "R4", or "R5".
  3. 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.
  4. 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:

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:
  1. fhirData - a FHIR Questionnaire resource (parsed). If you run into a problem, please open an issue on the LForms repository.
  2. 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:
  1. 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.
  2. 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.
  3. formData - an LHC-Forms form definition or data object. This can be obtained by converting a FHIR Questionnaire.
  4. 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:

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:
  1. 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.
  2. noEmptyValue - (default false) Remove items that have an empty value
  3. 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:
  1. 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.
  2. 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.
  3. noEmptyValue - (default false) If this is true, items that have an empty value will be removed.
  4. 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