luci-base: form.js: implement AbstractValue.retain property

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>
This commit is contained in:
Jo-Philipp Wich 2021-12-09 15:09:34 +01:00
parent ac64c70436
commit f5fbecf132

View file

@ -1347,6 +1347,7 @@ var CBIAbstractValue = CBIAbstractElement.extend(/** @lends LuCI.form.AbstractVa
this.default = null; this.default = null;
this.size = null; this.size = null;
this.optional = false; this.optional = false;
this.retain = false;
}, },
/** /**
@ -1369,6 +1370,17 @@ var CBIAbstractValue = CBIAbstractElement.extend(/** @lends LuCI.form.AbstractVa
* @default false * @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. * Sets a default value to use when the underlying UCI option is not set.
* *
@ -1979,29 +1991,37 @@ var CBIAbstractValue = CBIAbstractElement.extend(/** @lends LuCI.form.AbstractVa
* validation constraints. * validation constraints.
*/ */
parse: function(section_id) { parse: function(section_id) {
var active = this.isActive(section_id), var active = this.isActive(section_id);
cval = this.cfgvalue(section_id),
fval = active ? this.formvalue(section_id) : null;
if (active && !this.isValid(section_id)) { if (active && !this.isValid(section_id)) {
var title = this.stripTags(this.title).trim(); var title = this.stripTags(this.title).trim(),
var error = this.getValidationError(section_id); error = this.getValidationError(section_id);
return Promise.reject(new TypeError( return Promise.reject(new TypeError(
_('Option "%s" contains an invalid input value.').format(title || this.option) + ' ' + error)); _('Option "%s" contains an invalid input value.').format(title || this.option) + ' ' + error));
} }
if (fval != '' && fval != null) { if (active) {
if (this.forcewrite || !isEqual(cval, fval)) 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 (this.forcewrite || !isEqual(cval, fval)) {
return Promise.resolve(this.write(section_id, fval)); return Promise.resolve(this.write(section_id, fval));
}
} }
else { else if (!this.retain) {
if (!active || this.rmempty || this.optional) { return Promise.resolve(this.remove(section_id));
return Promise.resolve(this.remove(section_id));
}
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)));
}
} }
return Promise.resolve(); return Promise.resolve();
@ -3970,7 +3990,7 @@ var CBIFlagValue = CBIValue.extend(/** @lends LuCI.form.FlagValue.prototype */ {
else else
return Promise.resolve(this.write(section_id, fval)); return Promise.resolve(this.write(section_id, fval));
} }
else { else if (!this.retain) {
return Promise.resolve(this.remove(section_id)); return Promise.resolve(this.remove(section_id));
} }
}, },