luci-base: show validation message in error 5442/head
authorLukas Voegl <lvoegl@tdt.de>
Wed, 13 Oct 2021 10:20:48 +0000 (12:20 +0200)
committerLukas <lvoegl@tdt.de>
Tue, 26 Oct 2021 10:31:05 +0000 (12:31 +0200)
Signed-off-by: Lukas Voegl <lvoegl@tdt.de>
modules/luci-base/htdocs/luci-static/resources/form.js
modules/luci-base/htdocs/luci-static/resources/ui.js
modules/luci-base/htdocs/luci-static/resources/validation.js

index 4016007742b5a464e94225208367d67e4da1588c..cf09a1da905d2f0628752a26b4ae8e11bdf1ed4f 100644 (file)
@@ -601,7 +601,7 @@ var CBIMap = CBIAbstractElement.extend(/** @lends LuCI.form.Map.prototype */ {
                                if (!silent) {
                                        ui.showModal(_('Save error'), [
                                                E('p', {}, [ _('An error occurred while saving the form:') ]),
-                                               E('p', {}, [ E('em', { 'style': 'white-space:pre' }, [ e.message ]) ]),
+                                               E('p', {}, [ E('em', { 'style': 'white-space:pre-wrap' }, [ e.message ]) ]),
                                                E('div', { 'class': 'right' }, [
                                                        E('button', { 'class': 'cbi-button', 'click': ui.hideModal }, [ _('Dismiss') ])
                                                ])
@@ -1910,6 +1910,20 @@ var CBIAbstractValue = CBIAbstractElement.extend(/** @lends LuCI.form.AbstractVa
                return elem ? elem.isValid() : true;
        },
 
+       /**
+        * Returns the current validation error for this input.
+        *
+        * @param {string} section_id
+        * The configuration section ID
+        *
+        * @returns {string}
+        * The validation error at this time
+        */
+       getValidationError: function (section_id) {
+               var elem = this.getUIElement(section_id);
+               return elem ? elem.getValidationError() : '';
+       },
+
        /**
         * Test whether the option element is currently active.
         *
@@ -1971,7 +1985,9 @@ var CBIAbstractValue = CBIAbstractElement.extend(/** @lends LuCI.form.AbstractVa
 
                if (active && !this.isValid(section_id)) {
                        var title = this.stripTags(this.title).trim();
-                       return Promise.reject(new TypeError(_('Option "%s" contains an invalid input value.').format(title || this.option)));
+                       var 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) {
@@ -3877,7 +3893,9 @@ var CBIFlagValue = CBIValue.extend(/** @lends LuCI.form.FlagValue.prototype */ {
 
                        if (!this.isValid(section_id)) {
                                var title = this.stripTags(this.title).trim();
-                               return Promise.reject(new TypeError(_('Option "%s" contains an invalid input value.').format(title || this.option)));
+                               var error = this.getValidationError(section_id);
+                               return Promise.reject(new TypeError(
+                                       _('Option "%s" contains an invalid input value.').format(title || this.option) + ' ' + error));
                        }
 
                        if (fval == this.default && (this.optional || this.rmempty))
index 9cc62c12db1a1612e21e07811c6a9dba9af32f8c..9f3e74b93562a912669f6dcb82b527c8da671136 100644 (file)
@@ -155,6 +155,18 @@ var UIElement = baseclass.extend(/** @lends LuCI.ui.AbstractElement.prototype */
                return (this.validState !== false);
        },
 
+       /**
+        * Returns the current validation error
+        *
+        * @instance
+        * @memberof LuCI.ui.AbstractElement
+        * @returns {string}
+        * The validation error at this time
+        */
+       getValidationError: function() {
+               return this.validationError || '';
+       },
+
        /**
         * Force validation of the current input value.
         *
@@ -243,10 +255,12 @@ var UIElement = baseclass.extend(/** @lends LuCI.ui.AbstractElement.prototype */
 
                this.node.addEventListener('validation-success', L.bind(function(ev) {
                        this.validState = true;
+                       this.validationError = '';
                }, this));
 
                this.node.addEventListener('validation-failure', L.bind(function(ev) {
                        this.validState = false;
+                       this.validationError = ev.detail.message;
                }, this));
        },
 
index 70d3a7e73a10415c6bc4d42322234288d6776931..ce5c1ed540889cca398dc340a50977c9c334a766 100644 (file)
@@ -61,9 +61,15 @@ var Validator = baseclass.extend({
                        valid = this.vstack[0].apply(this, this.vstack[1]);
 
                if (valid !== true) {
-                       this.field.setAttribute('data-tooltip', _('Expecting: %s').format(this.error));
+                       var message = _('Expecting: %s').format(this.error);
+                       this.field.setAttribute('data-tooltip', message);
                        this.field.setAttribute('data-tooltip-style', 'error');
-                       this.field.dispatchEvent(new CustomEvent('validation-failure', { bubbles: true }));
+                       this.field.dispatchEvent(new CustomEvent('validation-failure', {
+                               bubbles: true,
+                               detail: {
+                                       message: message
+                               }
+                       }));
                        return false;
                }
 
@@ -74,7 +80,12 @@ var Validator = baseclass.extend({
                        this.assert(false, valid);
                        this.field.setAttribute('data-tooltip', valid);
                        this.field.setAttribute('data-tooltip-style', 'error');
-                       this.field.dispatchEvent(new CustomEvent('validation-failure', { bubbles: true }));
+                       this.field.dispatchEvent(new CustomEvent('validation-failure', {
+                               bubbles: true,
+                               detail: {
+                                       message: valid
+                               }
+                       }));
                        return false;
                }