Observation and Disease templates


Observation template

Observation templates are used to capture observations during an encounter in a pre-defined format. You could define observation templates to capture both general/non-disease-specific (e.g. Operation notes) information and condition/disease specific (e.g. Anaemia)  information.

To the user, an observation template shows up as an input form in the "Consultation" user interface. While in the back end, the observation template is modelled as a concept set. The form fields can be customised by defining/modifying concepts within the concept set.

Finally, to display an observation template on the Consultation UI, add the new concept set to the "All Observation Templates" concept set.


Disease template

A disease template can be defined by using one or more observation templates, one observation template each for a type of encounter.

For example, a disease template for Diabetes can be composed of 2 observation templates : "Diabetes intake" and "Diabetes follow-up".

To the user, a disease template looks like a set of UI forms in the "Consultation" user interface. You can configure the patient dashboard or visit page to display the observations captured using a disease template. In the back end, disease template is modelled as a concept set with the observation templates as the set members.

To make the disease template appear on the patient dashboard, add that concept set to the "All Disease Templates" concept set and modify the dashboard configurations.

General guidelines to define observation templates and concepts

  • When naming a concept and concept set, try to define a unique but concise name.

  • Provide description only when you want that description to show up in the observations tab as a help text.

  • Provide a short name always. If short name is absent, the fully specified name would be displayed in the UI.
  • Do not use special characters except ,; if possible in fully specified name of the concept. This is just based on the convention followed in the community.

  • Make sure that concepts meant for disease outcomes are defined in the Progress template and not intake template.

  • There can be observations made on concept of class "diagnosis" but they are different from diagnosis made via diagnosis tab.
  • When naming concepts in a short form (not short name) for example like "Anaemia, Diagnosed Date" use capitalisation but when concept name reads like a phrase then use "Anaemia, Reason for ntreatment" sentence casing. Follow the same for short name as well.
    Use short forms only in short name. Use short forms only if they are well understood, e.g. TB. For short forms always use uppercase. 
  • Identify concepts which are used as answers to the coded concepts. The data type for these concepts would be always N/A. If these are medical terminology then it might be present in the CIEL dictionary. Search for it and if found use the same name for the fully specified name of the concept.
  • Do not look for a concept set in CIEL dictionary.

Naming Convention

Disease Template Concept Sets

  • Add "template" to the Fully specified name to avoid naming collision with other concepts usually used for diagnosis.
  • Short name is displayed on the UI, hence give a clear and concise name for the short name 

Fully Specified Name = Anaemia Templates, Short Name = Anaemia
Fully Specified Name = Anaemia Intake Template, Short Name = Anaemia - Intake (note there is no comma in FN)

Fully Specified Name = Anaemia Progress Template, Short Name = Anaemia - Progress (note there is no comma in FN)

Concept Data Types

1Coded - Autocomplete with only coded values

Use it when you have fixed set of answers for a concept
"Death Note, Primary Cause of Death": {
          "required": true,
          "answersConceptName": "Death Note, Cause, Answers",
          "autocomplete": true


  "Death Note, Primary Cause of Death" = Concept which has answers
2Coded - Autocomplete with coded values and non-coded values
You need to define following hierarchy of concepts (taking example of Chief Complaints here).
Here's the OpenMRS concept structure level.

  • Chief Complaint Data (Is Set=true, class=Concept Details)
    • Chief Complaint (DataType=Coded)
    • Non-Coded Chief Complaint (DataType=Text)
  • Chief Complaint Answers (DataType=Coded)

You can add Chief Complaint data to a concept-set which you are using for your form to show in Observations tab. 
All the coded answers should be added to Chief Complaint Answers and not Chief Complaint. This is a hack for now because of inability to ignore loading of children when loading a concept. When we load children it slows down the loading of the form.

"Chief Complaint Data": {
"answersConceptName": "Chief Complaint Answers",
"autocomplete": true,
"codedConceptName": "Chief Complaint",
"nonCodedConceptName": "Non-Coded Chief Complaint",
"durationRequired": false,
"allowAddMore" : true

If either of codedConceptName or nonCodedConceptName is not given, It will be treated as autocomplete with only coded values.
The name of this configuration can be either "Chief Complaint Data" or "Chief Complaint"
which is the name of <Concept Set> or <Concept Set Member whose DataType is coded>.

For multiselect configuration, Add the following to the config map

"multiSelect": true instead of "autocomplete": true 
3Text - Free text type
"Chief Complaint Notes: {
"conciseText": true 
4Boolean - For Yes/No type
"Posture" : {
"buttonSelect" : true
5Numeric - For numerical values

Usage: Recommended to be configured only when the numbers would be small like number of children, pregnancies etc 
"No of children" : {
"stepper": true
6Date - For dates (without time) 
7Datetime - For dates with time 
8N/A - No data type

Usage: This is used for concepts which are used as answer to some other concept


Concept Data Conditions

Any concept in the parent concept set can be enabled / disabled conditionally based on the other concepts value. This makes the long forms usable and intuitive to use. These conditions can also be used to show errors on the forms as well.


In the below example, "Chief Complaint Notes" is editable only if the "Chief Complaint" concept is filled.


The configuration to enable the sample condition is shown below

File: /openmrs/apps/clinical/formConditions.js

// Bahmni.ConceptSet.FormConditions.rules is a map with key as the <concept name> that matches with the currently changed element in the observation form
Bahmni.ConceptSet.FormConditions.rules = {
  '<concept name>': function(formName, formFieldValues) {
		// This function gets 2 parameters
		// 'formName' will be the concept name of the form in which a value has been changed. ("History and Examination" in the above gif)
		// 'formFieldValues' is a map with key as concept name and value as its current value
		//    All the editable fields like 'Chief Complaint', 'Chief Complaint Notes', 'History Notes' will be present with their values as seen on the screen
		return {enable: [], disable: [], error: ""};
		// This method SHOULD return a map with two keys 'enable' and 'disable' with string array containing the concept names that needs to be enabled or disabled. You can return an error message to display in the UI with the 'error' variable.



Bahmni.ConceptSet.FormConditions.rules = {		//This is a constant that Bahmni expects
  'Chief Complaint Data': function(formName, formFieldValues) {//'Chief Complaint Data' concept when edited, triggers this function
        var conditions = {enable: [], disable: []};
        var chiefComplaint = formFieldValues['Chief Complaint'];
        var nonCodedChiefComplaint = formFieldValues['Non-Coded Chief Complaint'];
        if(chiefComplaint || nonCodedChiefComplaint) {
            conditions.enable.push("Chief Complaint Notes")
        } else {
			conditions.error = "Chief Complaint is not entered."
            conditions.disable.push("Chief Complaint Notes")
        return conditions; //Return object SHOULD be a map with 'enable' and 'disable' arrays having the concept names

The configuration to enable or disable form based on multiselect


Bahmni.ConceptSet.FormConditions.rules = {	
  'Tuberculosis, Type': function(formName, formFieldValues) {
	var conditions = {enable: [], disable: []};
	var selectedValues = formFieldValues['Tuberculosis, Type'];
	var found = _.contains(selectedValues, "Pulmonary") && _.contains(selectedValues, "Extrapulmonary")
	if(found) {
	} else {


Concept Classes

While in most cases you can choose you class yourself, Bahmni recognises some classes for its functionality.

Computed - When this class is used then field would show up as read-only in the observations tab of clinical module the,  which can be overridden manually.

Concept Details -

CSV Upload feature for creating templates


  1. Create and upload a concept CSV file. (Choose the option- concept while uploading the CSV)
    Sample concept CSV file: Delivery_concepts.csv
  2. Create and upload a concept set CSV file. (Choose the option- concept set while uploading the CSV)
    Sample concept CSV file: Delivery_concept_sets.csv


Naming convention for CSV files:

  1. Concept CSV file: <Disease>_concepts.csv
    Example: Anaemia_concepts.csv
  2. Concept set CSV file: <Disease>_concept_sets.csv
    Example: Anaemia_concept_sets.csv
  3. Avoid using short forms in filename like - TB_concepts.csv , use Tuberculosis_concepts.csv instead. 

CSV examples for Observation Templates and generic concepts can be found at:





On this Page

The Bahmni documentation is licensed under Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)