return true;
},
+ /**
+ * Get the validator function for the widget, handling both single functions
+ * and arrays of functions.
+ *
+ * @private
+ * @param {string} section_id
+ * The configuration section ID
+ *
+ * @returns {function}
+ * Returns a bound validator function suitable for passing to UI widgets.
+ * If this.validate is an array, returns a wrapper that calls each validator
+ * serially. Otherwise returns the bound validate method.
+ */
+ getValidator(section_id) {
+ if (Array.isArray(this.validate)) {
+ const validators = this.validate;
+ const element = this;
+ return (value) => {
+ for (let val of validators) {
+ if (typeof(val) === 'function') {
+ const result = val.call(element, section_id, value);
+ if (result !== true)
+ return result;
+ }
+ }
+ return true;
+ };
+ }
+ return L.bind(this.validate, this, section_id);
+ },
+
/**
* Test whether the input value is currently valid.
*
optional: this.optional || this.rmempty,
datatype: this.datatype,
select_placeholder: this.placeholder ?? placeholder,
- validate: L.bind(this.validate, this, section_id),
+ validate: this.getValidator(section_id),
disabled: (this.readonly != null) ? this.readonly : this.map.readonly
});
}
optional: this.optional || this.rmempty,
datatype: this.datatype,
placeholder: this.placeholder,
- validate: L.bind(this.validate, this, section_id),
+ validate: this.getValidator(section_id),
disabled: (this.readonly != null) ? this.readonly : this.map.readonly
});
}
optional: this.optional || this.rmempty,
datatype: this.datatype,
placeholder: this.placeholder,
- validate: L.bind(this.validate, this, section_id),
+ validate: this.getValidator(section_id),
disabled: (this.readonly != null) ? this.readonly : this.map.readonly
});
optional: this.optional,
orientation: this.orientation,
placeholder: this.placeholder,
- validate: L.bind(this.validate, this, section_id),
+ validate: this.getValidator(section_id),
disabled: (this.readonly != null) ? this.readonly : this.map.readonly
});
orientation: this.orientation,
select_placeholder: this.select_placeholder || this.placeholder,
custom_placeholder: this.custom_placeholder || this.placeholder,
- validate: L.bind(this.validate, this, section_id),
+ validate: this.getValidator(section_id),
disabled: (this.readonly != null) ? this.readonly : this.map.readonly
});
calcunits: this.calcunits,
disabled: this.readonly || this.disabled,
datatype: this.datatype,
- validate: L.bind(this.validate, this, section_id),
+ validate: this.getValidator(section_id),
});
this.widget = slider;
id: this.cbid(section_id),
value_enabled: this.enabled,
value_disabled: this.disabled,
- validate: L.bind(this.validate, this, section_id),
+ validate: this.getValidator(section_id),
tooltip,
tooltipicon: this.tooltipicon,
disabled: (this.readonly != null) ? this.readonly : this.map.readonly
create: this.create,
display_items: this.display_size ?? this.size ?? 3,
dropdown_items: this.dropdown_size ?? this.size ?? -1,
- validate: L.bind(this.validate, this, section_id),
+ validate: this.getValidator(section_id),
disabled: (this.readonly != null) ? this.readonly : this.map.readonly
});
cols: this.cols,
rows: this.rows,
wrap: this.wrap,
- validate: L.bind(this.validate, this, section_id),
+ validate: this.getValidator(section_id),
readonly: (this.readonly != null) ? this.readonly : this.map.readonly,
disabled: (this.disabled != null) ? this.disabled : null,
});
* It defaults to `string` which will allow any value.
* See {@link LuCI.validation} for details on the expression format.
*
- * @property {function} [validator]
- * Specifies a custom validator function which is invoked after the
- * standard validation constraints are checked. The function should return
- * `true` to accept the given input value. Any other return value type is
- * converted to a string and treated as validation error message.
+ * @property {function|function[]} [validator]
+ * Specifies one or more custom validator functions which are invoked after
+ * the standard validation constraints are checked. Each function should
+ * return `true` to accept the given input value. When multiple functions
+ * are provided as an array, they are executed serially and validation stops
+ * at the first function that returns a non-true value. Any non-true return
+ * value type is converted to a string and treated as a validation error
+ * message.
*
* @property {boolean} [disabled=false]
* Specifies whether the widget should be rendered in disabled state
* If an input element is not marked optional it must not be empty,
* otherwise it will be marked as invalid.
*
- * @param {function} [vfunc]
- * Specifies a custom validation function which is invoked after the
- * other validation constraints are applied. The validation must return
- * `true` to accept the passed value. Any other return type is converted
- * to a string and treated as validation error message.
+ * @param {function|function[]} [vfunc]
+ * Specifies a custom validation function or an array of validation functions
+ * which are invoked after the other validation constraints are applied. Each
+ * function must return `true` to accept the passed value. When multiple
+ * functions are provided as an array, they are executed serially and
+ * validation stops at the first function that returns a non-true value.
+ * Any non-true return type is converted to a string and treated as validation
+ * error message.
*
* @param {...string} [events=blur, keyup]
* The list of events to bind. Each received event will trigger a field