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
Shows 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.
Shows 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
A 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.
Represents 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 interface
Represents 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.
This 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.
A 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.
Shows 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.
Shows 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.
This 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.
Represents 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 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.
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.