luci-base: form.js: add AbstractValue.onchange property
authorJo-Philipp Wich <jo@mein.io>
Mon, 3 Aug 2020 13:34:07 +0000 (15:34 +0200)
committerJo-Philipp Wich <jo@mein.io>
Wed, 5 Aug 2020 11:51:16 +0000 (13:51 +0200)
Introduce a new, widget agnostic onchange property which allows setting
custom handler functions to react on element value changes.

Signed-off-by: Jo-Philipp Wich <jo@mein.io>
modules/luci-base/htdocs/luci-static/resources/form.js

index d5e3e941abe8bae184ffc05492403e9f755c30c8..c412fbf48081aeed13b53830b99d46e99fe630e2 100644 (file)
@@ -1374,6 +1374,21 @@ var CBIAbstractValue = CBIAbstractElement.extend(/** @lends LuCI.form.AbstractVa
         * @default null
         */
 
+       /**
+        * Register a custom value change handler.
+        *
+        * If this property is set to a function value, the function is invoked
+        * whenever the value of the underlying UI input element is changing.
+        *
+        * The invoked handler function will receive the DOM click element as
+        * first and the underlying configuration section ID as well as the input
+        * value as second and third argument respectively.
+        *
+        * @name LuCI.form.AbstractValue.prototype#onchange
+        * @type function
+        * @default null
+        */
+
        /**
         * Add a dependency contraint to the option.
         *
@@ -3120,6 +3135,20 @@ var CBIValue = CBIAbstractValue.extend(/** @lends LuCI.form.Value.prototype */ {
                        .then(this.renderFrame.bind(this, section_id, in_table, option_index));
        },
 
+       /** @private */
+       handleValueChange: function(section_id, state, ev) {
+               if (typeof(this.onchange) != 'function')
+                       return;
+
+               var value = this.formvalue(section_id);
+
+               if (isEqual(value, state.previousValue))
+                       return;
+
+               state.previousValue = value;
+               this.onchange.call(this, ev, section_id, value);
+       },
+
        /** @private */
        renderFrame: function(section_id, in_table, option_index, nodes) {
                var config_name = this.uciconfig || this.section.uciconfig || this.map.config,
@@ -3189,6 +3218,9 @@ var CBIValue = CBIAbstractValue.extend(/** @lends LuCI.form.Value.prototype */ {
                if (depend_list && depend_list.length)
                        optionEl.classList.add('hidden');
 
+               optionEl.addEventListener('widget-change',
+                       L.bind(this.handleValueChange, this, section_id, {}));
+
                optionEl.addEventListener('widget-change',
                        L.bind(this.map.checkDepends, this.map));