Reusable JavaScript solutions for creating dependent dropdown fields in REDCap using an External Module such as Shazam.
REDCap does not natively support dynamic filtering of dropdown choices within the same form without saving or reloading the page.
This repository provides two complementary approaches:
| Version | Use case |
|---|---|
| Explicit Mapping | Custom relationships, small or medium lists |
| Hierarchical Code (multi-chain) | Multi-level filtering using structured codes |
Both approaches improve user experience by updating dropdowns immediately on the client side.
-
Add your fields in REDCap:
- controlling variable(s)
- dependent dropdown(s)
-
Paste the JavaScript into your External Module
(e.g., Shazam) -
Configure the script depending on the version you choose
This version uses a mapping object to define relationships between values.
Best for:
- simple dependencies
- non-hierarchical data
- small to medium lists
var variable_controladora = 'specialty';
var variable_dependiente = 'specialist_name';
var mapa_opciones = {
'1': [
{ value: '1.1', label: 'Option A1' },
{ value: '1.2', label: 'Option A2' }
],
'2': [
{ value: '2.1', label: 'Option B1' },
{ value: '2.2', label: 'Option B2' }
]
};
-
Both fields must be dropdown lists
-
Choice codes and labels used in the script must match those defined in REDCap
-
Labels containing apostrophes must be escaped:
{ value: '8.1', label: 'O\'Higgins' }
This version uses hierarchical codes to define relationships automatically.
It supports one or multiple independent hierarchical chains within the same form.
The script:
- reads the selected value
- extracts the hierarchical part of the code
- identifies direct children
- filters the next dropdown
- supports multiple independent chains
var separator = '.'; // defines hierarchy levels
var metadataSeparator = '::'; // optional (advanced use)
The script is based on a key principle:
π Use the value to represent hierarchy, not raw data
7
7.1
7.1.1
7.2
π Clean and simple hierarchy
Some systems use formatted codes:
7
7.01
7.01.01
7.01.10.01
Here:
.is part of the format- not strictly a hierarchy separator
π This can break the filtering logic if used directly as values
If you need to preserve complex codes, you can separate:
- hierarchy (used by the script)
- additional code (kept intact)
1::2026
1|1::01.01.2026
1|2::01.02.2026
1|1|1::01.01.2026.A
π The script uses only the part before ::
| Value | Hierarchy used | Extra code |
|---|---|---|
| 1 | 1::01.01.2026 | 1 |
Use it only if:
- you must keep an existing coding system
- your codes contain formatting (e.g., dates, accounting codes)
Otherwise:
π Do not use it
π keep values simple
-
The
separatordefines hierarchy levels -
It must NOT appear inside level values
-
metadataSeparatoris optional -
It must appear at most once per value
The script filters only:
π direct children (one level down)
Example:
- Selecting
7shows:7|1,7|2
- NOT:
7|1|1
var chains = [
{
levels: ['region', 'province', 'city']
}
];
var chains = [
{
levels: ['region', 'province', 'city']
},
{
levels: ['service', 'unit', 'room']
}
];
regionβprovinceβcityserviceβunitβroomcategoryβsubcategoryβitem
Each chain works independently.
Example (mapping version):
- controlling variable:
specialty - dependent variable:
specialist_name
Example (hierarchical version):
regionprovincecity
Use an External Module such as:
- Shazam
- or any custom JS injector
- change controlling value
- verify dependent dropdown updates immediately
- verify invalid selections are cleared
- This is a UI-level solution
- It does not validate imported data (CSV/API)
- If a parent value changes, dependent values may reset
- Requires correct field configuration
This script filters available choices in the browser and should be considered a user-interface convenience, not a security control or server-side validation mechanism.
If the parent-child relationship is critical for data integrity, it should also be enforced or validated using an appropriate REDCap server-side or native mechanism.
The security of the mechanism used to inject the JavaScript into REDCap, such as an External Module or JavaScript injector, should also be evaluated separately.
Check:
- field names match exactly
- fields are dropdown lists
- values are correctly coded
- hierarchical structure is consistent
- Keep dropdown values documented
- Use consistent coding systems
- Avoid mixing hierarchy and raw data
- Use
metadataSeparatoronly when necessary
Part of the JavaScript structure and documentation was refined with the assistance of ChatGPT.
English is not my first language, so please excuse any wording issues.
MIT

.gif)