diff --git a/guacamole/src/main/frontend/src/app/form/directives/form.js b/guacamole/src/main/frontend/src/app/form/directives/form.js
index 81f500fc9..8d35774c7 100644
--- a/guacamole/src/main/frontend/src/app/form/directives/form.js
+++ b/guacamole/src/main/frontend/src/app/form/directives/form.js
@@ -86,6 +86,7 @@ angular.module('form').directive('guacForm', [function form() {
controller: ['$scope', '$injector', function formController($scope, $injector) {
// Required services
+ var formService = $injector.get('formService');
var translationStringService = $injector.get('translationStringService');
/**
@@ -134,6 +135,22 @@ angular.module('form').directive('guacForm', [function form() {
};
+ /**
+ * Returns an object as would be provided to the ngClass directive
+ * that defines the CSS classes that should be applied to the given
+ * form.
+ *
+ * @param {Form} form
+ * The form to generate the CSS classes for.
+ *
+ * @return {!Object.}
+ * The ngClass object defining the CSS classes for the given
+ * form.
+ */
+ $scope.getFormClasses = function getFormClasses(form) {
+ return formService.getClasses('form-', form);
+ };
+
/**
* Determines whether the given object is a form, under the
* assumption that the object is either a form or a field.
diff --git a/guacamole/src/main/frontend/src/app/form/directives/formField.js b/guacamole/src/main/frontend/src/app/form/directives/formField.js
index fbc0cfecf..4fcead1d6 100644
--- a/guacamole/src/main/frontend/src/app/form/directives/formField.js
+++ b/guacamole/src/main/frontend/src/app/form/directives/formField.js
@@ -155,6 +155,21 @@ angular.module('form').directive('guacFormField', [function formField() {
};
+ /**
+ * Returns an object as would be provided to the ngClass directive
+ * that defines the CSS classes that should be applied to this
+ * field.
+ *
+ * @return {!Object.}
+ * The ngClass object defining the CSS classes for the current
+ * field.
+ */
+ $scope.getFieldClasses = function getFieldClasses() {
+ return formService.getClasses('labeled-field-', $scope.field, {
+ empty: !$scope.model
+ });
+ };
+
/**
* Returns whether the current field should be displayed.
*
diff --git a/guacamole/src/main/frontend/src/app/form/services/formService.js b/guacamole/src/main/frontend/src/app/form/services/formService.js
index 0e9155c09..d2ac6be73 100644
--- a/guacamole/src/main/frontend/src/app/form/services/formService.js
+++ b/guacamole/src/main/frontend/src/app/form/services/formService.js
@@ -91,7 +91,7 @@ angular.module('form').provider('formService', function formServiceProvider() {
* @type FieldType
*/
'USERNAME' : {
- templateUrl : 'app/form/templates/textField.html'
+ templateUrl : 'app/form/templates/usernameField.html'
},
/**
@@ -272,6 +272,53 @@ angular.module('form').provider('formService', function formServiceProvider() {
};
+ /**
+ * Given form content and an arbitrary prefix, returns a corresponding
+ * CSS class object as would be provided to the ngClass directive that
+ * assigns a content-specific CSS class based on the prefix and
+ * form/field name. Generated class names follow the lowercase with
+ * dashes naming convention. For example, if the prefix is "field-" and
+ * the provided content is a field with the name "Swap red/blue", the
+ * object { 'field-swap-red-blue' : true } would be returned.
+ *
+ * @param {!string} prefix
+ * The arbitrary prefix to prepend to the name of the generated CSS
+ * class.
+ *
+ * @param {!(Form|Field)} [content]
+ * The form or field whose name should be used to produce the CSS
+ * class name.
+ *
+ * @param {Object.} [object={}]
+ * The optional base ngClass object that should be used to provide
+ * additional name/value pairs within the returned object.
+ *
+ * @return {!Object.}
+ * The ngClass object based on the provided object and defining a
+ * CSS class name for the given content.
+ */
+ service.getClasses = function getClasses(prefix, content, object) {
+
+ // Default to no additional properties
+ object = object || {};
+
+ // Perform no transformation if there is no content or
+ // corresponding name
+ if (!content || !content.name)
+ return object;
+
+ // Transform content name and prefix into lowercase-with-dashes
+ // CSS class name
+ var className = prefix + content.name.replace(/[^a-zA-Z0-9]+/g, '-').toLowerCase();
+
+ // Add CSS class name to provided base object (without touching
+ // base object)
+ var classes = angular.extend({}, object);
+ classes[className] = true;
+ return classes;
+
+ };
+
/**
* Compiles and links the field associated with the given name to the given
* scope, producing a distinct and independent DOM Element which functions
diff --git a/guacamole/src/main/frontend/src/app/form/templates/checkboxField.html b/guacamole/src/main/frontend/src/app/form/templates/checkboxField.html
index 80666c018..39d1f6b7d 100644
--- a/guacamole/src/main/frontend/src/app/form/templates/checkboxField.html
+++ b/guacamole/src/main/frontend/src/app/form/templates/checkboxField.html
@@ -1,7 +1,10 @@
-
+