luci-base: form.js: implement AbstractValue.retain property
authorJo-Philipp Wich <jo@mein.io>
Thu, 9 Dec 2021 14:09:34 +0000 (15:09 +0100)
committerJo-Philipp Wich <jo@mein.io>
Thu, 9 Dec 2021 14:11:07 +0000 (15:11 +0100)
The new `retain` boolean property controls whether the related option value
is purged from the configuration when the dependencies of the option are
not satisifed.

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

index 2be5bbce86c0679ab5417da8b066021764c49a6b..312d83605ddabbf315985eacf406c4bdf83563c1 100644 (file)
@@ -1347,6 +1347,7 @@ var CBIAbstractValue = CBIAbstractElement.extend(/** @lends LuCI.form.AbstractVa
                this.default = null;
                this.size = null;
                this.optional = false;
+               this.retain = false;
        },
 
        /**
@@ -1369,6 +1370,17 @@ var CBIAbstractValue = CBIAbstractElement.extend(/** @lends LuCI.form.AbstractVa
         * @default false
         */
 
+       /**
+        * If set to `true`, the underlying ui input widget value is not cleared
+        * from the configuration on unsatisfied depedencies. The default behavior
+        * is to remove the values of all options whose dependencies are not
+        * fulfilled.
+        *
+        * @name LuCI.form.AbstractValue.prototype#retain
+        * @type boolean
+        * @default false
+        */
+
        /**
         * Sets a default value to use when the underlying UCI option is not set.
         *
@@ -1979,30 +1991,38 @@ var CBIAbstractValue = CBIAbstractElement.extend(/** @lends LuCI.form.AbstractVa
         * validation constraints.
         */
        parse: function(section_id) {
-               var active = this.isActive(section_id),
-                   cval = this.cfgvalue(section_id),
-                   fval = active ? this.formvalue(section_id) : null;
+               var active = this.isActive(section_id);
 
                if (active && !this.isValid(section_id)) {
-                       var title = this.stripTags(this.title).trim();
-                       var error = this.getValidationError(section_id);
+                       var title = this.stripTags(this.title).trim(),
+                           error = this.getValidationError(section_id);
+
                        return Promise.reject(new TypeError(
                                _('Option "%s" contains an invalid input value.').format(title || this.option) + ' ' + error));
                }
 
-               if (fval != '' && fval != null) {
-                       if (this.forcewrite || !isEqual(cval, fval))
-                               return Promise.resolve(this.write(section_id, fval));
-               }
-               else {
-                       if (!active || this.rmempty || this.optional) {
-                               return Promise.resolve(this.remove(section_id));
+               if (active) {
+                       var cval = this.cfgvalue(section_id),
+                           fval = this.formvalue(section_id);
+
+                       if (fval == null || fval == '') {
+                               if (this.rmempty || this.optional) {
+                                       return Promise.resolve(this.remove(section_id));
+                               }
+                               else {
+                                       var title = this.stripTags(this.title).trim();
+
+                                       return Promise.reject(new TypeError(
+                                               _('Option "%s" must not be empty.').format(title || this.option)));
+                               }
                        }
-                       else if (!isEqual(cval, fval)) {
-                               var title = this.stripTags(this.title).trim();
-                               return Promise.reject(new TypeError(_('Option "%s" must not be empty.').format(title || this.option)));
+                       else if (this.forcewrite || !isEqual(cval, fval)) {
+                               return Promise.resolve(this.write(section_id, fval));
                        }
                }
+               else if (!this.retain) {
+                       return Promise.resolve(this.remove(section_id));
+               }
 
                return Promise.resolve();
        },
@@ -3970,7 +3990,7 @@ var CBIFlagValue = CBIValue.extend(/** @lends LuCI.form.FlagValue.prototype */ {
                        else
                                return Promise.resolve(this.write(section_id, fval));
                }
-               else {
+               else if (!this.retain) {
                        return Promise.resolve(this.remove(section_id));
                }
        },