Forms 2.0

This document will help people understand the available react component for building forms using Form Designer.  Also, it will explain how developers can compose the controls and make a composite control. 


List of Available components

The following are the list of available components

NameDescriptionImportant Properties
Label

Responsible for showing up messages on the form.  Can be hidden if required and has internationalization support.  A translationKey can be passed as part of the input metadata.

units,  value, translationKey
TextBoxShows up a text box on the form.  Performs validations for the input provided.  Accepts a list of validations as input and performs it.  Some out-of-the-box validations are available - like mandatory, allow decimal, min/max and dates are available.  The onChange event can be handled by the parent component by passing in a callback.

enabled,formFieldPath, 

onChange,

NumericBoxShows up a numeric box on the form.  Supports min and max and a bunch of validations similar to TextBox.  The onChange event can be handled by the parent component by passing in a callback.  The control accepts lowNormal, hiNormal and shows up on the UI as a range beside the textbox.  It supports 2 kinds of validations - allowRange & minMaxRange

hiAbsolute, hiNormal,

lowAbsolute,

lowNormal, value, onChange

ComplexControlA Wrapper component that takes in any registered component by name (props: conceptHandler) and creates a child component.  For e.g. you created a custom component called Disposition, then you can configure it in the form using this WrapperComponent.

addMore, conceptHandler,

onChange, showNotification

ObsControlRepresents an Observation in Bahmni Forms.  Takes in associated concept, label to show on the UI and a bunch of properties like mandatory, allowDecimal, position on the form etc.  Leverages the other components like Label, TextBox to form a composite control.  Can be created using a form designer interfaceSample ObsControl

ObsGroupControlRepresents an Observation Group in Bahmni Forms.  Takes in a concept set as input and constructs a bunch of observations represented as a group.   It accepts a controls array which takes in ObsControls and places them on the form based on the relative position of the ObsControl. Sample metadata looks like this
AutoCompleteThis component is a wrapper around react-select which is an auto-complete textbox.  The data source for the autocomplete can be static or dynamic.  A callback of onValueChanged is triggered once the new value is selected by the user.
DropDownA wrapper around AutoComplete component and is a displays a dropdown in the form.
BooleanControlA simple "Yes/No" button list that a user can select.  The labels on the button are configurable.  Whenever a value is changed, the onChange callback is triggered to the calling component.
RadioButtonA wrapper around HTML radio button that is "Form Aware".  It can track errors and bubble up to the parent.  The validations can be expressed on while creating the component and the value can be captured using the onValueChange event.
ButtonShows up a button on the form.  Has an option to be configured as a multi-select option button
CodedControlShows up a dropdown or auto-complete with a bunch of concept answers for a given concept.   Has an option to choose multi select or single select.  If a property of "autocomplete" is selected as true, an autocomplete control is shown.
DateShows up a date control on the form.  Simple wrapper around HTML input field of type date. Supports validation, error highlighting and ability for parent components to handle on change events.
DateTimeShows up date and time controls on the form. Simple wrapper around HTML input field of type date and time. Supports validation, error highlighting and ability for parent components to handle on change events.
SectionRepresents a separator on the form.  It doesn't represent any data that needs to be saved in the database.  Its just a way to visually categorize data on the form.
ImageRepresents an image on the form. Supports validation, error highlighting and ability for parent components to handle on change events.
VideoProvides an ability to upload and preview videos in the form. Supports validation, error highlighting and ability for parent components to handle on change events.  
LocationA wrapper around AutoComplete that provides an ability to show a bunch of openmrs locations in a dropdown.  A notification message is shown if the location cannot be retrieved.
ProviderA wrapper around AutoComplete that provides an ability to show a bunch of openmrs providers in a dropdown.  A notification message is shown if the providers cannot be retrieved.
FreeTextAutoCompleteThis component is a wrapper around react-select which is an auto-complete creatable textbox.  The data source for the autocomplete can be static or dynamic.  A callback of onValueChanged is triggered once the new value is selected by the user.
ContainerRepresents a form which is a composition of a bunch of other form controls.

Understanding Container Component

The Container component represents a "form" and is composed by other components like ObsControl, ObsGroupControl (see list above).  It is driven by a metadata json and leverages the base components to construct the form.  Leveraging React's component architecture, the container pushes the events like "Add More" & Validations to the children using props and the children handle it appropriately.  It dynamically creates the child components based on the "name" parameter in metadata.

Adding Custom Components & Understanding Component Store

You can write your own react components and register them so that they can be used in the forms.  This a very powerful feature because it provides a path for implementations to extend their own components. There is an object called ComponentStore available on window object where you can register/de-register your components.  The global window object is available in your app where you can access the ComponentStore and register your component.  Look at how TextBox component gets registered using the component store.

Designer Components

Designer Components are those components that are seen in "Design Mode" while creating a form in "Form Designer".  For e.g., you can drag and drop a Numeric Component (watch the video here).  So, for every new component that you want to drag-and-drop and configure using the "Form Designer", you need to have a designer version of it.  Essentially, it defines the "part of json" that needs to be generated for the dragged component which gets added to the overall form definition.  Every designer component defines a method "getJsonDefinition()" that returns the json identified by the component.  The metadata contains a field called designerProperties.isTopLevelComponent that specifies if this form element can be configured as a top-level-component.  Like any other custom component, the designer components can also be registered using the same process as discussed in previous section.

Internationalization

Forms leverage react-intl and provides support for internationalization out-of-the-box.  For e.g. the labels have a metadata property called "translationKey".  The Container component which renders the form accepts a list of translations as input and will be leveraged for translating the relevant translationKey in the child components.  The following Container spec gives an idea of how it works.

Accompanying Videos

Playlist of Form Builder videos in youtube




On this page