@darkobits/formation
Version:
306 lines (252 loc) • 9.67 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
exports.$registerComponent = $registerComponent;
exports.$getNextId = $getNextId;
exports.$getShowErrorsOnStr = $getShowErrorsOnStr;
exports.$getPrefixedName = $getPrefixedName;
exports.registerControl = registerControl;
exports.FormationConfigurator = FormationConfigurator;
var _ramda = require('ramda');
var _app = require('../../app');
var _app2 = _interopRequireDefault(_app);
var _FormationControl = require('../../classes/FormationControl');
var _constants = require('../constants');
var _interfaces = require('../interfaces');
var _utils = require('../utils');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
// ----- Private Data ----------------------------------------------------------
/**
* Set to true during Angular's configuration phase to prevent Formation
* configuration.
*
* @type {boolean}
*/
var allowConfiguration = true;
/**
* @private
*
* Configured component prefix.
*
* @type {string}
*/
var prefix = _constants.DEFAULT_PREFIX;
/**
* @private
*
* Global setting for error behavior.
*
* @type {string}
*/
var showErrorsOnStr = void 0;
/**
* @private
*
* Counter for getNextId(), used to assign unique IDs to unnamed forms.
*
* @type {number}
*/
var counter = -1;
/**
* @private
*
* Maintains a list of all components and directives registered with the
* service.
*
* @type {array}
*/
var registeredComponents = [];
// ----- Semi-Private Functions ------------------------------------------------
/**
* Adds the provided name to the list of registered components.
*
* @param {string} name
*/
function $registerComponent(name, definition) {
registeredComponents.push(name);
_app2.default.config(['$compileProvider', function ($compileProvider) {
if (typeof definition === 'function') {
$compileProvider.directive((0, _utils.lowercaseFirst)(name), definition);
} else {
$compileProvider.component((0, _utils.lowercaseFirst)(name), definition);
}
}]);
}
/**
* Returns the next available ID, used for assigning ID attributes to
* unnamed form instances.
*
* @private
*
* @return {number}
*/
function $getNextId() {
return ++counter;
}
/**
* Returns globally-configured error flags.
*
* @private
*
* @return {string}
*/
function $getShowErrorsOnStr() {
return showErrorsOnStr;
}
/**
* Returns a prefixed version of the provided string.
*
* @private
*
* Formation.$getPrefixedName('Input') // => 'fmInput';
*
* @param {string} name
* @return {string}
*/
function $getPrefixedName(name) {
return '' + (prefix || _constants.DEFAULT_PREFIX) + (0, _utils.capitalizeFirst)(name);
}
/**
* Curried assertType.
*
* Remaining arguments:
*
* @param {function|array} types
* @param {string} label
* @param {any} value
*
* @return {boolean}
*/
var check = (0, _utils.assertType)('FormationConfigurator');
// ----- Public Functions ------------------------------------------------------
/**
* Registers a Formation control as an Angular component using the provided
* name and component definition object.
*
* @param {string} name - Control name. Will be prefixed using the configured
* or default prefix.
* @param {object} definition - Component definition object.
*/
function registerControl(name, definition) {
var _bindings;
var normalizedName = (0, _utils.lowercaseFirst)($getPrefixedName(name));
$registerComponent(normalizedName, (0, _utils.mergeDeep)({
bindings: (_bindings = {}, _defineProperty(_bindings, _constants.COMPONENT_CONFIGURATION, '<config'), _defineProperty(_bindings, '$ngDisabled', '<ngDisabled'), _bindings),
require: _defineProperty({}, _constants.FORM_CONTROLLER, '^^' + _constants.FORM_COMPONENT_NAME)
}, definition));
}
/**
* Allows consumers to configure Formation behavior.
*
* @param {object} opts
* @param {string} [opts.showErrorsOn] - Comma/space-delimited string of control
* or form states that, when true, will cause ngMessage errors to display.
* @param {string} [opts.prefix] - Overrides the default component prefix for
* all formation controls.
*/
function FormationConfigurator(opts) {
if (!allowConfiguration) {
(0, _utils.throwError)('Formation cannot be configured once Angular has bootstrapped.');
}
check(Object, 'options', opts);
if (check([String, undefined], 'showErrorsOn', opts.showErrorsOn)) {
showErrorsOnStr = opts.showErrorsOn;
}
if (check([String, undefined], 'prefix', opts.prefix)) {
prefix = opts.prefix;
}
}
// ----- Decorators ------------------------------------------------------------
_app2.default.config(['$provide', function ($provide) {
// Disallow configuration once the application has started bootstrapping.
allowConfiguration = false;
var decorate = [
// Decoration spec for form/ngForm.
{
directives: ['formDirective', 'ngFormDirective'],
require: ['?^^fm'],
postLink: function postLink(scope, element, attributes, controllers) {
// Get a reference to the Angular Form controller.
var _controllers = _slicedToArray(controllers, 1),
ngFormController = _controllers[0];
// Get a reference to parent Formation forms, if any. Use 'propEq'
// here rather than 'is' to avoid a circular dependence between this
// module and Form.js.
var fmFormController = (0, _ramda.find)(function (controller) {
return (0, _ramda.path)(['constructor', _constants.FORM_CONTROLLER], controller);
}, controllers);
if (fmFormController && (0, _utils.isFunction)(fmFormController[_interfaces.RegisterNgForm])) {
fmFormController[_interfaces.RegisterNgForm](ngFormController);
}
}
},
// Decoration spec for ngModel.
{
directives: ['ngModelDirective'],
require: (0, _ramda.map)(function (component) {
return '?^^' + component;
}, registeredComponents),
postLink: function postLink(scope, element, attributes, controllers) {
// Get a reference to the ngModel controller.
var _controllers2 = _slicedToArray(controllers, 1),
ngModelController = _controllers2[0];
// Get a reference to parent Formation controls, if any.
var fmComponentController = (0, _ramda.find)((0, _ramda.is)(_FormationControl.FormationControl), controllers);
// Get a reference to parent Formation forms, if any. Use 'propEq'
// here rather than 'is' to avoid a circular dependence between this
// module and Form.js.
var fmFormController = (0, _ramda.find)(function (controller) {
return (0, _ramda.path)(['constructor', _constants.FORM_CONTROLLER], controller);
}, controllers);
if (fmComponentController && (0, _utils.isFunction)(fmComponentController[_interfaces.RegisterNgModel])) {
// If we are the child of a Formation control, register with the
// control.
fmComponentController[_interfaces.RegisterNgModel](ngModelController);
} else if (fmFormController && (0, _utils.isFunction)(fmFormController[_interfaces.RegisterNgModel])) {
// Otherwise, if we are the child of a Formation form, register with
// the form.
fmFormController[_interfaces.RegisterNgModel](ngModelController);
}
}
}];
decorate.forEach(function () {
var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
directives = _ref.directives,
require = _ref.require,
postLink = _ref.postLink;
directives.forEach(function (directiveName) {
$provide.decorator(directiveName, ['$delegate', function ($delegate) {
var _$delegate = _slicedToArray($delegate, 1),
directiveSpec = _$delegate[0];
var compile = directiveSpec.compile;
// Add requires.
directiveSpec.require = (0, _ramda.concat)(directiveSpec.require || [], require);
directiveSpec.compile = function () {
// Invoke original compile to get link object.
var link = Reflect.apply(compile, this, arguments);
// Return new link object.
return {
pre: function pre() {
if ((0, _utils.isFunction)(link.pre)) {
// Invoke original pre-link.
Reflect.apply(link.pre, this, arguments);
}
},
post: function post() {
if ((0, _utils.isFunction)(link.post)) {
// Invoke original post-link.
Reflect.apply(link.post, this, arguments);
}
// Invoke new post-link.
Reflect.apply(postLink, this, arguments);
}
};
};
return $delegate;
}]);
});
});
}]);