Skip to content

Data validation in the internal framework

  • The internal framework ships with a ready-to-use validation layer.
  • When we add inputs or dropdowns, we rarely need custom JavaScript—the HTML attributes define the behaviour.
  • Give each field an id that follows the convention (input_… or dropdown_…) and a data-validate JSON block describing its rules.
  • On DOMContentLoaded, load_input() / load_dropdown() store each element in structure.inputs/structure.dropdowns and attach listeners. Every change runs input_enforceRules() or dropdown_enforceRules(), which sanitises the value, updates current_value, and toggles the valid flag.
  • Group related fields by sharing the same rule_name. Any button whose data-validate equals that string automatically enables/disables when the group is valid.
<!-- Inputs -->
<input
id="input_customer_name"
data-validate='{
"rule_name":"customerBlock",
"rules":["minLength:1"],
"required":true,
"show_error":true,
"show_ok":false,
"error_header":"Missing name",
"error_text":"Please enter the customer name",
"valid":false
}'
/>
<select
id="dropdown_customer_state"
data-validate='{
"rule_name":"customerBlock",
"rules":["nonDefault"],
"required":true,
"show_error":true,
"error_header":"State required",
"error_text":"Pick a state",
"valid":false
}'
>
<option value="">Select state</option>
<option value="ka">Karnataka</option>
<option value="mh">Maharashtra</option>
</select>
<!-- Button -->
<button
id="button_customer_save"
class="ankur_disabled ankur_btn_1"
data-validate="customerBlock"
data-click='{"operation":"function","function_name":"save_customer"}'
>
Save Customer
</button>

Quick recipe: give every input/dropdown you want to validate together the same rule_name inside data-validate, then set the button’s data-validate to that exact string. That’s it—the framework now knows those controls belong together.

How it works:

  1. load_input() and load_dropdown() register both fields and store rule_name: "customerBlock".
  2. When the user types, input_enforceRules() trims/filters input, sets dataValidate.valid = true/false, and calls validateByRule("input_customer_name","input").
  3. validateByRule gathers every element sharing that rule_name, checks whether required ones are valid, and toggles any button whose data-validate is the same string. In this case button_customer_save becomes enabled once both fields are valid.
<!-- Section A -->
<input
id="input_order_id"
data-validate='{"rule_name":"orderBlock","rules":["digits"],"required":true,"valid":false}'
/>
<input
id="input_order_amount"
data-validate='{"rule_name":"orderBlock","rules":["digits","noDecimals"],"required":true,"valid":false}'
/>
<button
id="button_order_submit"
class="ankur_disabled ankur_btn_1"
data-validate="orderBlock"
data-click='{"operation":"function","function_name":"submit_order"}'
>
Submit Order
</button>
<!-- Section B -->
<input
id="input_payment_ref"
data-validate='{"rule_name":"paymentBlock","rules":["minLength:6"],"required":true,"valid":false}'
/>
<select
id="dropdown_payment_mode"
data-validate='{"rule_name":"paymentBlock","rules":["nonDefault"],"required":true,"valid":false}'
>
<option value="">Select mode</option>
<option value="upi">UPI</option>
<option value="card">Card</option>
</select>
<button
id="button_payment_save"
class="ankur_disabled ankur_btn_1"
data-validate="paymentBlock"
data-click='{"operation":"function","function_name":"save_payment"}'
>
Save Payment
</button>
  • Inputs in Section A share rule_name: "orderBlock"; Section B uses "paymentBlock". Each button listens only to its own group, so the sections operate independently on the same page without extra JS.
  • rule_name can be any string; the framework uses exact matching.
  • Surface validation icons by toggling show_ok / show_error inside data-validate.
  • Optional fields can set "required": false; they block the button only if they contain a value but fail validation.
  • Need to check a group manually? Call button_validateByRule("ruleName") to reuse the same logic and built-in alert flow.

With these conventions, you wire validation entirely through markup, letting internal.js manage state, sanitisation, and button enablement automatically.

3. Two buttons sharing the same validation rule

Section titled “3. Two buttons sharing the same validation rule”
  • Question
    For the menu_share_batch section, both buttons (Send to Nursery, Send to Farmer) use data-validate="language_selection".
    Historically only one button per menu had validation. Here:

    • Both buttons should be disabled until a language is selected.
    • It works for Send to Farmer but not for Send to Nursery.
    • Are there examples where multiple buttons share a validation rule and both are enabled by validation?
  • Answer
    Validation is wired like this:

    • Inputs/dropdowns with data-validate='{"rule_name":"X", ...}' share a rule name (e.g. "language_selection").
    • Buttons with data-validate="X" get scope = "X" in load_button().
    • validateByRule(id, "dropdown") finds all inputs/dropdowns with rule_name === "X" and then enables/disables all buttons whose scope === "X".

    In your HTML:

    <select id="dropdown_language_selection"
    data-validate='{"rule_name":"language_selection", ...}'>
    ...
    <a id="button_language_selection_price"
    data-validate="language_selection" ...>Send to Nursery</a>
    <a id="button_language_selection_change"
    data-validate="language_selection" ...>Send to Farmer</a>

    The issue was that Send to Nursery did not have the ankur_disabled class initially, so it started enabled and stayed enabled until a change event happened. Fix:

    • Add ankur_disabled to the Nursery button so both start disabled.
    • Ensure dropdown_enforceRules/validateByRule run when the menu opens (so both buttons reflect validation state).

4. How does validation connect inputs and buttons?

Section titled “4. How does validation connect inputs and buttons?”
  • Question
    “In the framework, data validate rules is defined, if input and button have the same name, they get connected for validation… how exactly does that mapping work?”

  • Answer

    • load_dropdown() and load_input() parse data-validate JSON and store dataValidate.rule_name into structure.dropdowns / structure.inputs.
    • load_button() reads data-validate="ruleName" on buttons and stores it as button.scope.
    • validateByRule(id, type):
      • Reads ruleName from the triggering input/dropdown.
      • Collects all inputs + dropdowns whose dataValidate.rule_name === ruleName.
      • Checks each for required and valid.
      • Finds all buttons where button.scope === ruleName and enables/disables them based on overall validity.

    So multiple buttons can share the same rule by using the same data-validate="ruleName" value.