diff --git a/javascript/src/Element/FormGroup.js b/javascript/src/Element/FormGroup.js
index 0d893d32ecc5b83505009969b94c719a1889b3fc..622b9331fbf4c2a4c0544d11fa6199d86174c34e 100644
--- a/javascript/src/Element/FormGroup.js
+++ b/javascript/src/Element/FormGroup.js
@@ -86,88 +86,39 @@ QfqNS.Element = QfqNS.Element || {};
         return this.$helpBlock.length > 0;
     };
 
+    /**
+     * @deprecated
+     *
+     * Read-only is mapped onto setEnabled(). We do not distinguish between those two.
+     *
+     * @param readonly
+     */
+    n.FormGroup.prototype.setReadOnly = function (readonly) {
+        this.setEnabled(!readonly);
+    };
+
     n.FormGroup.prototype.setEnabled = function (enabled) {
-        this.$formGroup.data("enabled", enabled);
         this.$element.prop('disabled', !enabled);
 
-        // Test if we're not readonly, if so set classes. This is required because we share `text-muted` with the
-        // readonly-state
-        if (this.$formGroup.data("readonly") !== true) {
-            if (enabled) {
-                this.$formGroup.removeClass("text-muted");
-            } else {
-                this.$formGroup.addClass("text-muted");
-            }
-        }
-
         if (enabled) {
+            this.$formGroup.removeClass("text-muted");
             this.$label.removeClass("disabled");
-            this.$element.parents("div[class=radio]").removeClass("disabled");
+            this.$element.parents("div.radio").removeClass("disabled");
         } else {
+            this.$formGroup.addClass("text-muted");
             this.$label.addClass("disabled");
-            this.$element.parents("div[class=radio]").addClass("disabled");
-        }
-    };
-
-    n.FormGroup.prototype.setReadOnly = function (readonly) {
-        this.$formGroup.data("readonly", readonly);
-        this.$element.prop('readonly', readonly);
-        this.handleReadOnlyEmulationIfRequired(readonly);
-
-        // Test if we're enabled, if so set classes. This is required because we share `text-muted` with the
-        // enabled-state
-        if (this.$formGroup.data("enabled") !== false) {
-            if (readonly) {
-                this.$formGroup.addClass("text-muted");
-            } else {
-                this.$formGroup.removeClass("text-muted");
-            }
-        }
-
-        if (readonly) {
-            this.$label.addClass("readonly");
-        } else {
-            this.$formGroup.removeClass("readonly");
+            this.$element.parents("div.radio").addClass("disabled");
         }
     };
 
-    /**
-     * @private
-     * @param readonlyState
-     */
-    n.FormGroup.prototype.handleReadOnlyEmulationIfRequired = function (readonlyState) {
-        if (!this.readOnlyEmulationRequired()) {
-            return;
-        }
-
-        if (readonlyState) {
-            // In case we're called with readonlyState===true twice in a row, make sure only one handler will be
-            // active at a time
-            this.$element.off('click', this.readOnlyHandler);
-            this.$element.on('click', this.readOnlyHandler);
+    n.FormGroup.prototype.setHidden = function (hidden) {
+        if (hidden) {
+            this.$formGroup.addClass("hidden");
         } else {
-            this.$element.off('click', this.readOnlyHandler);
+            this.$formGroup.removeClass("hidden");
         }
     };
 
-    n.FormGroup.prototype.readOnlyEmulationRequired = function () {
-        // Keep this at top, since select does not feature the type attribute.
-        if (n.readOnlyIgnored.indexOf(this.$element[0].nodeName.toLowerCase())) {
-            return true;
-        }
-
-        if (!this.$element[0].hasAttribute('type')) {
-            // if there is no type attribute, browsers default to text, which is `properly implements` read only.
-            return false;
-        }
-        if (n.readOnlyIgnored.indexOf(this.$element[0].getAttribute('type').toLowerCase())) {
-            return true;
-        }
-
-
-        return false;
-    };
-
 
     /**
      * Read Only click handler.
diff --git a/javascript/src/Helper/NameSpaceFunctions.js b/javascript/src/Helper/NameSpaceFunctions.js
index e4fb0da622d2044a5d3394eea4fa93b4a9d8bb66..8aa20845d2b6ffbd2ca3a6644c057c231b9dcc3b 100644
--- a/javascript/src/Helper/NameSpaceFunctions.js
+++ b/javascript/src/Helper/NameSpaceFunctions.js
@@ -15,4 +15,32 @@ QfqNS.Helper = QfqNS.Helper || {};
             errorThrown, "error");
         alert.show();
     };
+
+    n.stringToBool = function (string) {
+        if (typeof string !== "string") {
+            return string;
+        }
+        var lowerCase = string.toLowerCase().trim();
+
+        switch (lowerCase) {
+            case "1":
+            case "yes":
+            case "y":
+            case "t":
+            case "true":
+            case "enabled":
+            case "enable":
+                return true;
+            case "0":
+            case "no":
+            case "n":
+            case "f":
+            case "false":
+            case "disabled":
+            case "disable":
+                return false;
+            default:
+                return false;
+        }
+    };
 })(QfqNS.Helper);
\ No newline at end of file
diff --git a/javascript/src/QfqForm.js b/javascript/src/QfqForm.js
index 2cc32960def1cf6843c21b5b48e775932eb3a8b9..3cc8a806e7ed78abea9cf9cdb21b2d66bbbeed5a 100644
--- a/javascript/src/QfqForm.js
+++ b/javascript/src/QfqForm.js
@@ -69,10 +69,53 @@ var QfqNS = QfqNS || {};
             function (obj) {
                 n.Helper.showAjaxError(null, obj.textStatus, obj.errorThrown);
             });
+
+        var configurationData = this.readElementConfigurationData();
+
+        this.applyElementConfiguration(configurationData);
     };
 
     n.QfqForm.prototype.on = n.EventEmitter.onMixin;
 
+    /**
+     *
+     * @private
+     */
+    n.QfqForm.prototype.readElementConfigurationData = function () {
+        var $configuredElements = $("#" + this.formId + " [data-hidden],#" + this.formId + " [data-disabled]");
+
+        var configurationArray = [];
+        $configuredElements.each(function (index, element) {
+            try {
+                var $element = $(element);
+                if (!element.hasAttribute("name")) {
+                    n.Log.warning("Element has configuration data, but no name. Skipping");
+                    return;
+                }
+
+                var configuration = {};
+                configuration['form-element'] = $element.attr('name');
+
+                var hiddenVal = $element.data('hidden');
+                if (hiddenVal !== undefined) {
+                    configuration.hidden = n.Helper.stringToBool(hiddenVal);
+                }
+
+                var disabledVal = $element.data('disabled');
+                if (disabledVal !== undefined) {
+                    configuration.disabled = n.Helper.stringToBool(disabledVal);
+                }
+
+                configurationArray.push(configuration);
+            } catch (e) {
+                n.Log.error(e.message);
+            }
+        });
+
+        return configurationArray;
+
+    };
+
     /**
      * @public
      * @param bsTabs
@@ -634,12 +677,17 @@ var QfqNS = QfqNS || {};
                 }
 
                 if (configurationItem.readonly !== undefined) {
-                    element.setReadOnly(configurationItem.readonly);
+                    // Readonly and disabled is the same in our domain
+                    element.setEnabled(!configurationItem.readonly);
                 }
 
                 if (configurationItem.disabled !== undefined) {
+                    // Readonly and disabled is the same in our domain
                     element.setEnabled(!configurationItem.disabled);
+                }
 
+                if (configurationItem.hidden !== undefined) {
+                    element.setHidden(configurationItem.hidden);
                 }
             } catch (e) {
                 n.Log.error(e.message);
diff --git a/mockup/elementconfiguration.html b/mockup/elementconfiguration.html
index fad1efb7fda9ea4b5869bd23f32e8a1902802591..6569d7db84788423ef69b30badd08bfa4934b1d6 100644
--- a/mockup/elementconfiguration.html
+++ b/mockup/elementconfiguration.html
@@ -89,7 +89,7 @@
             </div>
 
             <div class="col-md-6">
-                <input id="text" type="text" class="form-control" name="text">
+                <input id="text" type="text" class="form-control" name="text" data-disabled="true">
             </div>
 
         </div>
@@ -141,7 +141,7 @@
             <div class="col-md-6">
                 <div class="checkbox">
                     <label>
-                        <input type="checkbox" id="checkbox" name="checkbox">
+                        <input type="checkbox" id="checkbox" name="checkbox" data-hidden="no">
                     </label>
 
                     <p class="help-block"></p>
diff --git a/mockup/readonly.html b/mockup/readonly.html
index 0ac97f6739841ea4ebf95b09c427bc6492d64773..8ac01fe082797863790083e9e2a1807d89352479 100644
--- a/mockup/readonly.html
+++ b/mockup/readonly.html
@@ -110,7 +110,7 @@
     $(function () {
         var textInput, select, radio, checkbox;
 
-        textInput = new QfqNS.Element.Text($('#text'));
+        textInput = new QfqNS.Element.Textual($('#text'));
         select = new QfqNS.Element.Select($('#select'));
         radio = new QfqNS.Element.Radio($('input[type=radio]'));
         checkbox = new QfqNS.Element.Checkbox($('#checkbox'));