Dynamic Dropdowns
- Create a simple
divwith classesinput-style has-borders no-icon mb-5 - Inside the div
- A
labelwith id that begins withtext_and classcolor-highlight ankur_language - A
selectelement with id that begins withdropdown_and classankur_language - An
optionelement with valuedefault, and attributesdisabled selectedandstyle="display: none"textYour Text Here - An
ielement with a check icon class and adisabled valid color-grass-darkclass - An
ielement with a times icon class and adisabled invalid color-red-darkclass
- A
<div class="input-style has-borders no-icon mb-5"> <label id="text_crop_step1" class="color-highlight ankur_language">Select Crop</label> <select id="dropdown_crop_step1" data-change='{"operation" : "function", "function_name" : "selected_crop_batch"}' data-validate='{"rule_name":"stepnext","rules":["nonDefault"],"required":true,"error_header":"Select Crop","error_text":"Please select crop to proceed","show_error":false,"show_ok":true,"language":true,"valid":false}' class="ankur_language" style="background-color: white !important" > <option value="default" disabled selected style="display: none">Select Crop</option> </select> <i class="fa fa-check disabled valid color-grass-dark"></i> <i class="fa fa-times disabled invalid color-red-dark"></i></div>Dynamic Dropdowns - How It Works
Section titled “Dynamic Dropdowns - How It Works”Introduction
Section titled “Introduction”Dynamic dropdowns in this framework automatically manage label visibility, validation states, and can be populated with data from APIs. The framework handles all state changes automatically when values are selected.
Initialization Flow
Section titled “Initialization Flow”1. Page Load
Section titled “1. Page Load”When the page loads, the framework automatically:
- Scans all
<select>elements with IDs starting withdropdown_ - Stores their initial state in
structure.dropdowns[]array - Captures default options, first option, and validation rules
2. Dropdown Instance Creation
Section titled “2. Dropdown Instance Creation”When you call dropdown("dropdown_id"):
- Creates a singleton instance (returns same instance if called multiple times)
- Links to the stored data in
structure.dropdowns[] - Sets up the first option as disabled placeholder
- Attaches a
changeevent listener - Calls
updateState()to set initial label visibility
What Happens When a Value is Selected
Section titled “What Happens When a Value is Selected”Step-by-Step Flow:
Section titled “Step-by-Step Flow:”-
User selects a value from the dropdown
-
Change event fires → The event listener attached in constructor executes:
this.element.addEventListener("change", () => {this.updateState(); // Update label visibilitythis.storedDropdown.current_selected = this.element.value; // Update stored valuethis.storedDropdown.current_selected_text = /* selected text */; // Update stored textdropdown_enforceRules(this.element.id); // Run validationif (this.onChangeCallback) {this.onChangeCallback(this.element.value); // Call custom callback if set}}); -
Label Visibility Update (
updateState()):- Checks if selected value exists AND is not the default value
- If valid: Adds
input-style-activeclass to parent → Label becomes visible - If default/empty: Removes
input-style-activeclass → Label becomes hidden
-
Validation Runs (
dropdown_enforceRules()):- Checks if value matches validation rules (e.g.,
nonDefault,required) - If valid:
- Shows green checkmark (removes
.disabledfrom.fa-check) - Hides red X (adds
.disabledto.fa-times) - Hides required message (adds
.disabledto<em>)
- Shows green checkmark (removes
- If invalid:
- Shows red X (removes
.disabledfrom.fa-times) - Hides green checkmark (adds
.disabledto.fa-check) - Shows required message (removes
.disabledfrom<em>)
- Shows red X (removes
- Checks if value matches validation rules (e.g.,
-
Custom Change Handler (if
data-changeattribute exists):- Framework parses the
data-changeJSON - If operation is “function”, calls the specified function
- Example:
selected_crop_batch()function is called when crop dropdown changes
- Framework parses the
Label Visibility Behavior
Section titled “Label Visibility Behavior”When Label is Visible:
Section titled “When Label is Visible:”- Condition: Selected value exists AND is not equal to the default first option value
- CSS Class: Parent div has
.input-style-activeclass - Visual: Label floats above the dropdown with white background
When Label is Hidden:
Section titled “When Label is Hidden:”- Condition: No value selected OR value equals default first option
- CSS Class: Parent div does NOT have
.input-style-activeclass - Visual: Label is invisible (opacity: 0, shifted right)
Automatic Updates:
Section titled “Automatic Updates:”- Label visibility updates automatically on every value change
- No manual intervention needed
- Works for both user selections and programmatic value changes
Validation Flow
Section titled “Validation Flow”Validation Rules (from data-validate attribute):
Section titled “Validation Rules (from data-validate attribute):”required: true- Field must have a non-default valuerules: ["nonDefault"]- Value cannot be the default placeholdershow_ok: true- Show green checkmark when validshow_error: true- Show red X when invalid
Validation Process:
Section titled “Validation Process:”User selects value ↓dropdown_enforceRules() called ↓Check if value is required and not default ↓Apply additional rules (nonDefault, specificValues, etc.) ↓If VALID: - Add .input-style-active (label visible) - Show green checkmark - Hide red X - Hide required message ↓If INVALID: - Remove .input-style-active (label hidden if default) - Show red X - Hide green checkmark - Show required messageCascading Dropdowns
Section titled “Cascading Dropdowns”How Cascading Works:
Section titled “How Cascading Works:”- Parent dropdown changes → Triggers
data-changehandler - Handler function executes (e.g.,
selected_crop_batch()) - Child dropdowns reset →
dropdown("child_id").reset() - API call made →
load_report()with parent’s selected value - Loading state shown →
dropdown("child_id").startLoading() - On success → Options added via
addOptionsBulk() - Loading stopped →
dropdown("child_id").stopLoading()
Example Flow:
Section titled “Example Flow:”// User selects "Tomato" from crop dropdownselected_crop_batch() { // 1. Reset dependent dropdowns dropdown("dropdown_variety_step1").reset();
// 2. Get selected value var crop_id = dropdown("dropdown_crop_step1").getValue();
// 3. Show loading dropdown("dropdown_variety_step1").startLoading();
// 4. Fetch data load_report("endpoint", { crop_id }, success_callback, error_callback);}
// On successstart_variety_list_success(response) { // 5. Process options var options = response.map(item => ({ value: String(item.variety_id), text: item.variety_name }));
// 6. Stop loading dropdown("dropdown_variety_step1").stopLoading();
// 7. Add options dropdown("dropdown_variety_step1").addOptionsBulk(options);
// 8. Auto-select if only one option if (options.length == 1) { dropdown("dropdown_variety_step1").setValue(options[0].value); }}Loading States
Section titled “Loading States”Show Loading:
Section titled “Show Loading:”dropdown("dropdown_id").startLoading();- Clears all options except first
- Shows animated “Loading…” text in first option
- Creates pulsing dot animation
Stop Loading:
Section titled “Stop Loading:”dropdown("dropdown_id").stopLoading();- Stops animation timer
- Restores default first option text
- Ready for options to be added
Programmatic Value Changes
Section titled “Programmatic Value Changes”Setting Value:
Section titled “Setting Value:”dropdown("dropdown_id").setValue("Tomato");- Finds option with matching value
- Sets dropdown value
- Updates stored state
- Triggers change event → Label updates, validation runs
- Same behavior as user selection
Getting Value:
Section titled “Getting Value:”var value = dropdown("dropdown_id").getValue(); // Returns selected valuevar text = dropdown("dropdown_id").getText(); // Returns selected textState Management
Section titled “State Management”Stored State (in structure.dropdowns[]):
Section titled “Stored State (in structure.dropdowns[]):”default_selected- Initial selected valuecurrent_selected- Current selected value (updates on change)current_selected_text- Current selected textdefault_options- Initial options from HTMLcurrent_options- Current options (can be modified dynamically)default_first- Initial first option (placeholder)current_first- Current first option
State Updates:
Section titled “State Updates:”- All state changes are stored in
structure.dropdowns[] - State persists across page interactions
reset()restores all default values
Key Methods
Section titled “Key Methods”Value Management:
Section titled “Value Management:”getValue()- Get current selected valuegetText()- Get current selected textsetValue(value)- Set value and trigger change eventempty()- Reset to default but keep options
Options Management:
Section titled “Options Management:”addOption(value, text, tag)- Add single optionaddOptionsBulk(optionsArray)- Add multiple optionsremoveOption(value)- Remove specific optionclearOptions()- Remove all except first option
State Management:
Section titled “State Management:”reset()- Restore to initial stateupdateState()- Update label visibilitystartLoading()- Show loading animationstopLoading()- Hide loading animation
Visibility/Enable:
Section titled “Visibility/Enable:”show()/hide()- Toggle visibilityenable()/disable()- Toggle disabled state
Important Notes
Section titled “Important Notes”-
First Option is Always Disabled: The first option (value=“default”) is always disabled and acts as a placeholder
-
Label Updates Automatically: No need to manually manage label visibility - it updates on every value change
-
Validation is Automatic: Validation runs automatically when value changes, no manual trigger needed
-
State is Centralized: All state is stored in
structure.dropdowns[], not just in DOM -
Singleton Pattern:
dropdown(id)returns the same instance, so you can safely call it multiple times -
Change Events Cascade: Setting value programmatically triggers the same change event as user selection
-
Loading State: Use
startLoading()before API calls andstopLoading()after receiving data -
Reset Clears Dynamic Options:
reset()removes all dynamically added options and restores defaults
Common Patterns
Section titled “Common Patterns”Pattern 1: Simple Dropdown
Section titled “Pattern 1: Simple Dropdown”// Initializedropdown("dropdown_id");
// User selects value → Label appears automatically// Validation runs automaticallyPattern 2: Cascading Dropdowns
Section titled “Pattern 2: Cascading Dropdowns”// Parent changes → Handler functionfunction onParentChange() { dropdown("child_id").reset(); dropdown("child_id").startLoading(); load_report("endpoint", params, success, error);}
// On successfunction success(response) { dropdown("child_id").stopLoading(); dropdown("child_id").addOptionsBulk(options);}Pattern 3: Pre-populated Dropdown
Section titled “Pattern 3: Pre-populated Dropdown”// Add optionsdropdown("dropdown_id").addOptionsBulk([ { value: "1", text: "Option 1" }, { value: "2", text: "Option 2" }]);
// Set initial valuedropdown("dropdown_id").setValue("1"); // Label appears automaticallySummary
Section titled “Summary”When a user selects a value:
- Change event fires
- Label visibility updates (adds/removes
.input-style-active) - Validation runs automatically
- Icons update (checkmark/X)
- Custom change handler executes (if defined)
- State is stored in
structure.dropdowns[]
Everything happens automatically - you just need to:
- Define the HTML structure
- Initialize with
dropdown(id) - Optionally add options dynamically
- The framework handles the rest!