diff --git a/platform/forms/src/controllers/CompositeController.js b/platform/forms/src/controllers/CompositeController.js index 2e91118fb5..36680a1eb0 100644 --- a/platform/forms/src/controllers/CompositeController.js +++ b/platform/forms/src/controllers/CompositeController.js @@ -5,18 +5,39 @@ define( function () { "use strict"; + /** + * The CompositeController supports the "composite" control type, + * which provides an array of other controls. It is used specifically + * to support validation when a particular row is not marked as + * required; in this case, empty input should be allowed, but partial + * input (where some but not all of the composite controls have been + * filled in) should be disallowed. This is enforced in the template + * by an ng-required directive, but that is supported by the + * isNonEmpty check that this controller provides. + * @constructor + */ function CompositeController() { + // Check if an element is defined; the map step of isNonEmpty function isDefined(element) { return typeof element !== 'undefined'; } + // Boolean or; the reduce step of isNonEmpty function or(a, b) { return a || b; } return { + /** + * Check if an array contains anything other than + * undefined elements. + * @param {Array} value the array to check + * @returns {boolean} true if any non-undefined + * element is in the array + */ isNonEmpty: function (value) { - return (value || []).map(isDefined).reduce(or, false); + return Array.isArray(value) && + value.map(isDefined).reduce(or, false); } }; } diff --git a/platform/forms/test/controllers/CompositeControllerSpec.js b/platform/forms/test/controllers/CompositeControllerSpec.js new file mode 100644 index 0000000000..0051c20eb4 --- /dev/null +++ b/platform/forms/test/controllers/CompositeControllerSpec.js @@ -0,0 +1,36 @@ +/*global define,describe,it,expect,beforeEach,waitsFor,jasmine*/ + +define( + ["../../src/controllers/CompositeController"], + function (CompositeController) { + "use strict"; + + describe("The composite controller", function () { + var controller; + + beforeEach(function () { + controller = new CompositeController(); + }); + + it("detects non-empty arrays", function () { + expect(controller.isNonEmpty(["a", "b", undefined])) + .toBeTruthy(); + expect(controller.isNonEmpty([3])) + .toBeTruthy(); + }); + + it("detects empty arrays", function () { + expect(controller.isNonEmpty([undefined, undefined, undefined])) + .toBeFalsy(); + expect(controller.isNonEmpty([])) + .toBeFalsy(); + }); + + it("ignores non-arrays", function () { + expect(controller.isNonEmpty("this is not an array")) + .toBeFalsy(); + }); + + }); + } +); \ No newline at end of file diff --git a/platform/forms/test/suite.json b/platform/forms/test/suite.json index b86d7b9178..f69c3a325e 100644 --- a/platform/forms/test/suite.json +++ b/platform/forms/test/suite.json @@ -1,5 +1,6 @@ [ "MCTControl", "MCTForm", + "controllers/CompositeController", "controllers/DateTimeController" ] \ No newline at end of file