diff --git a/javascript/src/Form.js b/javascript/src/Form.js
index ce4751f03f54e35fae50f54240e911f7eff5dbd8..f0ceb013a9f2c50353ff954358dbf2ffc250bd40 100644
--- a/javascript/src/Form.js
+++ b/javascript/src/Form.js
@@ -33,6 +33,8 @@ var QfqNS = QfqNS || {};
         this.formChanged = false;
         this.$form = $(document.forms[this.formId]);
         this.$form.on("change", this.changeHandler.bind(this));
+        this.$form.on("invalid.bs.validator", this.validationError.bind(this));
+        this.$form.on("valid.bs.validator", this.validationSuccess.bind(this));
 
         // On <input> elements, we specifically bind this events, in order to update the formChanged property
         // immediately, not only after loosing focus. Same goes for <textarea>
@@ -124,6 +126,20 @@ var QfqNS = QfqNS || {};
         return result;
     };
 
+    /**
+     * @private
+     */
+    n.Form.prototype.validationError = function (data) {
+        this.eventEmitter.emitEvent('form.validation.failed', n.EventEmitter.makePayload(this, {element: data.relatedTarget}));
+    };
+
+    /**
+     * @private
+     */
+    n.Form.prototype.validationSuccess = function (data) {
+        this.eventEmitter.emitEvent('form.validation.success', n.EventEmitter.makePayload(this, {element: data.relatedTarget}));
+    };
+
     /**
      * @public
      */
diff --git a/javascript/src/QfqForm.js b/javascript/src/QfqForm.js
index 960d44fcbb013aa7fed98333a8879b940cd15f5f..bff8f2e0f2f2beebc04c5706f6015c44c420bd90 100644
--- a/javascript/src/QfqForm.js
+++ b/javascript/src/QfqForm.js
@@ -91,17 +91,26 @@ var QfqNS = QfqNS || {};
         n.Helper.tinyMce();
         this.form.on('form.submit.before', n.Helper.tinyMce.prepareSave);
         this.form.on('form.validation.before', n.Helper.tinyMce.prepareSave);
-        this.form.on('form.validation.after', this.showHiddenErrors);
+        this.form.on('form.validation.failed', this.validationError);
+        this.form.on('form.validation.success', this.validationSuccess);
+
     };
 
     n.QfqForm.prototype.on = n.EventEmitter.onMixin;
 
-    /**
-     * @private
-     */
-    n.QfqForm.prototype.showHiddenErrors = function (info) {
-        if (info.data.validationResult === false) {
-            info.target.$form.find('.with-errors').filter('.hidden').removeClass('hidden');
+    n.QfqForm.prototype.validationError = function (info) {
+        var $formControl = $(info.data.element);
+        var $messageContainer = $formControl.siblings('.hidden.with-errors');
+        $messageContainer.data('qfq.hidden.message', true);
+        $messageContainer.removeClass('hidden');
+
+    };
+
+    n.QfqForm.prototype.validationSuccess = function (info) {
+        var $formControl = $(info.data.element);
+        var $messageContainer = $formControl.siblings('.with-errors');
+        if ($messageContainer.data('qfq.hidden.message') === true) {
+            $messageContainer.addClass('hidden');
         }
     };