ExtJs fields have validation mechanisms but they make the field invalid. To implement a field prompt mechanisms I have improved existing code and migrated it to 6.6.0 version.

 

 

In the following sample you can see the form bound “Submit” button, which will be disabled on standard error validation and enabled on minor validation. The border color, text color and icon are also changed to less aggressive orange.

Overriden classes:

Ext.define('overrides.form.field.Base', {
    override: 'Ext.form.field.Base',

    warningCls: Ext.baseCSSPrefix + 'form-warning',

    validateValue: function (value) {
        var isValid = this.callParent(arguments);

        if (isValid) {
            var warnings = this.getWarnings(),
                hasWarnings = !Ext.isEmpty(warnings);

            if (hasWarnings) {
                this.showWarnings(warnings);
            } else {
                this.clearWarnings();
            }
        } else {
            this.clearWarnings();
        }

        return isValid;
    },

    getWarnings: function (value) {
        value = arguments.length ? (value == null ? '' : value) : this.processRawValue(this.getRawValue());

        var warnings = [],
            warnator = this.warnator,
            wtype = this.wtype,
            vtypes = Ext.form.field.VTypes

        if (Ext.isFunction(warnator)) {
            msg = warnator.call(this, value);
            if (msg !== true) {
                warnings.push(msg);
            }
        }

        if (wtype) {
            if (!vtypes[wtype](value, this)) {
                warnings.push(this.wtypeText || vtypes[wtype + 'Text']);
            }
        }
        return warnings;
    },

    showWarnings: function (warnings) {
        this.setActiveWarnings(Ext.Array.from(warnings));
    },

    clearWarnings: function () {
        this.unsetActiveWarning();
    },

    getActiveWarning: function () {
        return this.activeWarning || '';
    },

    hasActiveWarning: function () {
        return !!this.getActiveWarning();
    },

    setActiveWarning: function (msg) {
        this.setActiveWarnings(msg);
    },

    getActiveWarnings: function () {
        return this.activeWarnings || [];
    },

    setActiveWarnings: function (warnings) {
        var errorWrapEl = this.errorWrapEl,
            msgTarget = this.msgTarget,
            isSide = msgTarget === 'side',
            isQtip = msgTarget === 'qtip',
            actionEl, activeWarning, tpl, targetEl;

        warnings = Ext.Array.from(warnings);
        tpl = this.lookupTpl('activeErrorsTpl');
        this.activeWarnings = warnings;
        activeWarning = this.activeWarning = tpl.apply({
            fieldLabel: this.fieldLabel,
            errors: warnings,
            listCls: Ext.baseCSSPrefix + 'list-plain'
        });

        this.renderActiveWarning();

        if (this.rendered) {
            actionEl = this.getActionEl();

            if (isSide) {
                this.errorEl.dom.setAttribute('data-errorqtip', activeWarning);
            } else if (isQtip) {
                actionEl.dom.setAttribute('data-errorqtip', activeWarning);
            } else if (msgTarget === 'title') {
                actionEl.dom.setAttribute('title', activeWarning);
            }

            if (msgTarget !== 'title') {
                this.ariaErrorEl.dom.innerHTML = warnings.join('. ');
                actionEl.dom.setAttribute('aria-describedby', this.ariaErrorEl.id);
            }

            if (isSide || isQtip) {
                Ext.form.Labelable.initTip();
            }

            if (!this.msgTargets[msgTarget]) {
                targetEl = Ext.get(msgTarget);

                if (targetEl) {
                    targetEl.dom.innerHTML = activeWarning;
                }
            }
        }

        if (errorWrapEl) {
            errorWrapEl.setVisible(warnings.length > 0);
            if (isSide && this.autoFitErrors) {
                this.labelEl.addCls(this.topLabelSideErrorCls);
            }
            this.updateLayout();
        }
    },

    unsetActiveWarning: function () {
        var errorWrapEl = this.errorWrapEl,
            msgTarget = this.msgTarget,
            restoreDisplay = this.restoreDisplay,
            actionEl, targetEl;

        if (this.hasActiveWarning()) {
            delete this.activeWarning;
            delete this.activeWarnings;
            this.renderActiveWarning();

            if (this.rendered) {
                actionEl = this.getActionEl();

                if (msgTarget === 'qtip') {
                    actionEl.dom.removeAttribute('data-errorqtip');
                } else if (msgTarget === 'title') {
                    actionEl.dom.removeAttribute('title');
                }

                if (msgTarget !== 'title') {
                    this.ariaErrorEl.dom.innerHTML = '';
                    actionEl.dom.removeAttribute('aria-describedby');
                }

                if (!this.msgTargets[msgTarget]) {
                    targetEl = Ext.get(msgTarget);

                    if (targetEl) {
                        targetEl.dom.innerHTML = '';
                    }
                }

                if (errorWrapEl) {
                    errorWrapEl.hide();
                    if (msgTarget === 'side' && this.autoFitErrors) {
                        this.labelEl.removeCls(this.topLabelSideErrorCls);
                    }
                    this.updateLayout();

                    if (restoreDisplay) {
                        this.el.dom.style.display = 'block';
                        this.restoreDisplay();
                    }
                }
            }
        }
    },

    renderActiveWarning: function () {
        var activeWarning = this.getActiveWarning(),
            hasError = !!activeWarning;

        if (activeWarning !== this.lastActiveWarning) {
            this.lastActiveWarning = activeWarning;
            this.fireEvent('errorchange', this, activeWarning);
        }

        if (this.rendered && !this.destroyed && !this.preventMark) {
            this.toggleWarningCls(hasError);
            if (this.errorEl) {
                this.errorEl.dom.innerHTML = activeWarning;
            }
        }
    },

    toggleWarningCls: function (hasError) {
        this.el[hasError ? 'addCls' : 'removeCls'](this.warningCls);
    }
});

 

Ext.define('overrides.form.field.Text', {
    override: 'Ext.form.field.Text',

   	triggerWrapWarningCls: Ext.baseCSSPrefix + 'form-trigger-wrap-default',
    inputWrapWarningCls: Ext.baseCSSPrefix + 'form-trigger-wrap-warning',

 	toggleWarningCls: function(hasError) {
        var method = hasError ? 'addCls' : 'removeCls';

        this.callParent(arguments);

        this.triggerWrap[method](this.triggerWrapWarningCls);
        this.inputWrap[method](this.inputWrapWarningCls);
    }
});

 

.x-form-trigger-wrap-default .x-form-trigger-wrap-warning {
    border-color: orange !important;
}

.x-form-warning .x-form-invalid-under-default {
    background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABqklEQVR4XqWTvWsUURTFf+/tx7DmA5sUmyB+EGQDCkFRxCFosYWCFgELm2ApCBYW/gOCFpYSrUMsBIv4BwTSCSqaWgsTEDRV2EVBZWffvXIYwhZOEdgLhzmcc+7h3WKCuzPOhI+P80rDzE7WwmAHIHnzVIxxl4qJVaKbkYrBxvyVZQRxaYcq0EmehvePzp5YnD67hCAuzd0PUWB2JNQazzo377D7+auAuDR51QWjZWxYvD2e34DsJw+fbwviSJOnTHWBO5aGt6fa84szF67CzguCIYgjTZ4yuP9fYGqO2avO8j348hSKff4OkiAuDXnKKDsqGD1989jSLWJvA/58g+YUv34Xgrg0eSij7MEpsXx66k62O932wjT030NjAuotXj/YE8SlyUMZZbWj3ejmEFubp69fg711yCYha0GWcXftjCAuTZ4yKKsd7dbNfHXuUk6jeAPNCSBCAJpGb78PiGel7gCmLHMXc76/21oNn57kfm5lFg0W0KBPDag7GoYBEuCUE0uy/fIH4cOjy27J0SlI56DEiSVFFi4dEUUIMRBrQZTzjDFj/87/ACmm3+QFX8sKAAAAAElFTkSuQmCC');
    color: orange !important;
}

 

Working sample.