blob: 518db7dba9f75a1af8aab0929e964fa5432025cf [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/**
* A directive that allows editing of a collection of fields.
*/
angular.module('form').directive('guacForm', [function form() {
return {
// Element only
restrict: 'E',
replace: true,
scope: {
/**
* The translation namespace of the translation strings that will
* be generated for all fields. This namespace is absolutely
* required. If this namespace is omitted, all generated
* translation strings will be placed within the MISSING_NAMESPACE
* namespace, as a warning.
*
* @type String
*/
namespace : '=',
/**
* The form content to display. This may be a form, an array of
* forms, or a simple array of fields.
*
* @type Form[]|Form|Field[]|Field
*/
content : '=',
/**
* The object which will receive all field values. Each field value
* will be assigned to the property of this object having the same
* name.
*
* @type Object.<String, String>
*/
model : '=',
/**
* Whether the contents of the form should be restricted to those
* fields/forms which match properties defined within the given
* model object. By default, all fields will be shown.
*
* @type Boolean
*/
modelOnly : '='
},
templateUrl: 'app/form/templates/form.html',
controller: ['$scope', '$injector', function formController($scope, $injector) {
// Required services
var translationStringService = $injector.get('translationStringService');
/**
* The array of all forms to display.
*
* @type Form[]
*/
$scope.forms = [];
/**
* The object which will receive all field values. Normally, this
* will be the object provided within the "model" attribute. If
* no such object has been provided, a blank model will be used
* instead as a placeholder, such that the fields of this form
* will have something to bind to.
*
* @type Object.<String, String>
*/
$scope.values = {};
/**
* Produces the translation string for the section header of the
* given form. The translation string will be of the form:
*
* <code>NAMESPACE.SECTION_HEADER_NAME<code>
*
* where <code>NAMESPACE</code> is the namespace provided to the
* directive and <code>NAME</code> is the form name transformed
* via translationStringService.canonicalize().
*
* @param {Form} form
* The form for which to produce the translation string.
*
* @returns {String}
* The translation string which produces the translated header
* of the form.
*/
$scope.getSectionHeader = function getSectionHeader(form) {
// If no form, or no name, then no header
if (!form || !form.name)
return '';
return translationStringService.canonicalize($scope.namespace || 'MISSING_NAMESPACE')
+ '.SECTION_HEADER_' + translationStringService.canonicalize(form.name);
};
/**
* Determines whether the given object is a form, under the
* assumption that the object is either a form or a field.
*
* @param {Form|Field} obj
* The object to test.
*
* @returns {Boolean}
* true if the given object appears to be a form, false
* otherwise.
*/
var isForm = function isForm(obj) {
return !!('name' in obj && 'fields' in obj);
};
// Produce set of forms from any given content
$scope.$watch('content', function setContent(content) {
// If no content provided, there are no forms
if (!content) {
$scope.forms = [];
return;
}
// Ensure content is an array
if (!angular.isArray(content))
content = [content];
// If content is an array of fields, convert to an array of forms
if (content.length && !isForm(content[0])) {
content = [{
fields : content
}];
}
// Content is now an array of forms
$scope.forms = content;
});
// Update string value and re-assign to model when field is changed
$scope.$watch('model', function setModel(model) {
// Assign new model only if provided
if (model)
$scope.values = model;
// Otherwise, use blank model
else
$scope.values = {};
});
/**
* Returns whether the given field should be displayed to the
* current user.
*
* @param {Field} field
* The field to check.
*
* @returns {Boolean}
* true if the given field should be visible, false otherwise.
*/
$scope.isVisible = function isVisible(field) {
// All fields are visible if contents are not restricted to
// model properties only
if (!$scope.modelOnly)
return true;
// Otherwise, fields are only visible if they are present
// within the model
return field && (field.name in $scope.values);
};
/**
* Returns whether at least one of the given fields should be
* displayed to the current user.
*
* @param {Field[]} fields
* The array of fields to check.
*
* @returns {Boolean}
* true if at least one field within the given array should be
* visible, false otherwise.
*/
$scope.containsVisible = function containsVisible(fields) {
// If fields are defined, check whether at least one is visible
if (fields) {
for (var i = 0; i < fields.length; i++) {
if ($scope.isVisible(fields[i]))
return true;
}
}
// Otherwise, there are no visible fields
return false;
};
}] // end controller
};
}]);