From 7f9236da98ac79d9d41f74ccb990b4b60499a164 Mon Sep 17 00:00:00 2001 From: Coleman Watts Date: Thu, 14 Jan 2021 13:39:22 -0500 Subject: [PATCH] Afform - convert afEntity and afField to components, standardize js filenames --- ext/afform/core/ang/af/Entity.js | 26 ------ ext/afform/core/ang/af/Field.js | 75 ----------------- ext/afform/core/ang/af/afEntity.component.js | 25 ++++++ ext/afform/core/ang/af/afField.component.js | 81 +++++++++++++++++++ ext/afform/core/ang/af/afField.html | 10 +-- .../{Fieldset.js => afFieldset.directive.js} | 0 .../ang/af/{Join.js => afJoin.directive.js} | 0 .../af/{Repeat.js => afRepeat.directive.js} | 1 + ext/afform/core/ang/af/afRepeat.html | 2 +- .../core/ang/af/fields/ChainSelect.html | 2 +- ext/afform/core/ang/af/fields/CheckBox.html | 8 +- ext/afform/core/ang/af/fields/Date.html | 2 +- ext/afform/core/ang/af/fields/Number.html | 2 +- ext/afform/core/ang/af/fields/Radio.html | 2 +- .../core/ang/af/fields/RichTextEditor.html | 2 +- ext/afform/core/ang/af/fields/Select.html | 2 +- ext/afform/core/ang/af/fields/Text.html | 2 +- ext/afform/core/ang/af/fields/TextArea.html | 2 +- 18 files changed, 125 insertions(+), 119 deletions(-) delete mode 100644 ext/afform/core/ang/af/Entity.js delete mode 100644 ext/afform/core/ang/af/Field.js create mode 100644 ext/afform/core/ang/af/afEntity.component.js create mode 100644 ext/afform/core/ang/af/afField.component.js rename ext/afform/core/ang/af/{Fieldset.js => afFieldset.directive.js} (100%) rename ext/afform/core/ang/af/{Join.js => afJoin.directive.js} (100%) rename ext/afform/core/ang/af/{Repeat.js => afRepeat.directive.js} (96%) diff --git a/ext/afform/core/ang/af/Entity.js b/ext/afform/core/ang/af/Entity.js deleted file mode 100644 index 2c522a6030..0000000000 --- a/ext/afform/core/ang/af/Entity.js +++ /dev/null @@ -1,26 +0,0 @@ -(function(angular, $, _) { - // Example usage: ...
- angular.module('af').directive('afField', function(crmApi4) { - return { - restrict: 'E', - require: ['^^afForm', '^^afFieldset', '?^^afJoin', '?^^afRepeatItem'], - templateUrl: '~/af/afField.html', - scope: { - fieldName: '@name', - defn: '=' - }, - link: function($scope, $el, $attr, ctrls) { - var ts = $scope.ts = CRM.ts('afform'), - closestController = $($el).closest('[af-fieldset],[af-join],[af-repeat-item]'), - afForm = ctrls[0], - boolOptions = [{id: true, label: ts('Yes')}, {id: false, label: ts('No')}], - // Only used for is_primary radio button - noOptions = [{id: true, label: ''}]; - $scope.dataProvider = closestController.is('[af-repeat-item]') ? ctrls[3] : ctrls[2] || ctrls[1]; - $scope.fieldId = afForm.getFormMeta().name + '-' + $scope.fieldName + '-' + id++; - - $el.addClass('af-field-type-' + _.kebabCase($scope.defn.input_type)); - - $scope.getOptions = function() { - return $scope.defn.options || ($scope.fieldName === 'is_primary' && $scope.defn.input_type === 'Radio' ? noOptions : boolOptions); - }; - - $scope.select2Options = function() { - return { - results: _.transform($scope.getOptions(), function(result, opt) { - result.push({id: opt.id, text: opt.label}); - }, []) - }; - }; - - // is_primary field - watch others in this afRepeat block to ensure only one is selected - if ($scope.fieldName === 'is_primary' && 'repeatIndex' in $scope.dataProvider) { - $scope.$watch('dataProvider.afRepeat.getEntityController().getData()', function (items, prev) { - var index = $scope.dataProvider.repeatIndex; - // Set first item to primary if there isn't a primary - if (items && !index && !_.find(items, 'is_primary')) { - $scope.dataProvider.getFieldData().is_primary = true; - } - // Set this item to not primary if another has been selected - if (items && prev && items.length === prev.length && items[index].is_primary && prev[index].is_primary && - _.filter(items, 'is_primary').length > 1 - ) { - $scope.dataProvider.getFieldData().is_primary = false; - } - }, true); - } - - // ChainSelect - watch control field & reload options as needed - if ($scope.defn.input_type === 'ChainSelect') { - $scope.$watch('dataProvider.getFieldData()[defn.input_attrs.controlField]', function(val) { - if (val) { - var params = { - where: [['name', '=', $scope.fieldName]], - select: ['options'], - loadOptions: ['id', 'label'], - values: {} - }; - params.values[$scope.defn.input_attrs.controlField] = val; - crmApi4($scope.dataProvider.getEntityType(), 'getFields', params, 0) - .then(function(data) { - $scope.defn.options = data.options; - }); - } - }); - } - } - }; - }); -})(angular, CRM.$, CRM._); diff --git a/ext/afform/core/ang/af/afEntity.component.js b/ext/afform/core/ang/af/afEntity.component.js new file mode 100644 index 0000000000..6f0fef14d2 --- /dev/null +++ b/ext/afform/core/ang/af/afEntity.component.js @@ -0,0 +1,25 @@ +(function(angular, $, _) { + // Whitelist of all allowed properties of an af-fieldset + // (at least the ones we care about client-side - other's can be added for server-side processing and we'll just ignore them) + var modelProps = { + type: '@', + data: '=', + modelName: '@name', + label: '@', + autofill: '@' + }; + // Example usage: ...
...
+ angular.module('af').component('afEntity', { + require: {afForm: '^afForm'}, + bindings: modelProps, + controller: function() { + + this.$onInit = function() { + var entity = _.pick(this, _.keys(modelProps)); + entity.id = null; + this.afForm.registerEntity(entity); + }; + } + + }); +})(angular, CRM.$, CRM._); diff --git a/ext/afform/core/ang/af/afField.component.js b/ext/afform/core/ang/af/afField.component.js new file mode 100644 index 0000000000..385038294f --- /dev/null +++ b/ext/afform/core/ang/af/afField.component.js @@ -0,0 +1,81 @@ +(function(angular, $, _) { + var id = 0; + // Example usage:
+ angular.module('af').component('afField', { + require: { + afFieldset: '^^afFieldset', + afJoin: '?^^afJoin', + afRepeatItem: '?^^afRepeatItem' + }, + templateUrl: '~/af/afField.html', + bindings: { + fieldName: '@name', + defn: '=' + }, + controller: function($scope, $element, crmApi4) { + var ts = $scope.ts = CRM.ts('afform'), + ctrl = this, + boolOptions = [{id: true, label: ts('Yes')}, {id: false, label: ts('No')}], + // Only used for is_primary radio button + noOptions = [{id: true, label: ''}]; + + this.$onInit = function() { + var closestController = $($element).closest('[af-fieldset],[af-join],[af-repeat-item]'); + $scope.dataProvider = closestController.is('[af-repeat-item]') ? ctrl.afRepeatItem : ctrl.afJoin || ctrl.afFieldset; + $scope.fieldId = ctrl.fieldName + '-' + id++; + + $element.addClass('af-field-type-' + _.kebabCase(ctrl.defn.input_type)); + + // is_primary field - watch others in this afRepeat block to ensure only one is selected + if (ctrl.fieldName === 'is_primary' && 'repeatIndex' in $scope.dataProvider) { + $scope.$watch('dataProvider.afRepeat.getEntityController().getData()', function (items, prev) { + var index = $scope.dataProvider.repeatIndex; + // Set first item to primary if there isn't a primary + if (items && !index && !_.find(items, 'is_primary')) { + $scope.dataProvider.getFieldData().is_primary = true; + } + // Set this item to not primary if another has been selected + if (items && prev && items.length === prev.length && items[index].is_primary && prev[index].is_primary && + _.filter(items, 'is_primary').length > 1 + ) { + $scope.dataProvider.getFieldData().is_primary = false; + } + }, true); + } + + // ChainSelect - watch control field & reload options as needed + if (ctrl.defn.input_type === 'ChainSelect') { + $scope.$watch('dataProvider.getFieldData()[defn.input_attrs.controlField]', function(val) { + if (val) { + var params = { + where: [['name', '=', ctrl.fieldName]], + select: ['options'], + loadOptions: ['id', 'label'], + values: {} + }; + params.values[ctrl.defn.input_attrs.controlField] = val; + crmApi4($scope.dataProvider.getEntityType(), 'getFields', params, 0) + .then(function(data) { + ctrl.defn.options = data.options; + }); + } + }); + } + + }; + + $scope.getOptions = function () { + return ctrl.defn.options || (ctrl.fieldName === 'is_primary' && ctrl.defn.input_type === 'Radio' ? noOptions : boolOptions); + }; + + $scope.select2Options = function() { + return { + results: _.transform($scope.getOptions(), function(result, opt) { + result.push({id: opt.id, text: opt.label}); + }, []) + }; + }; + + } + }); +})(angular, CRM.$, CRM._); diff --git a/ext/afform/core/ang/af/afField.html b/ext/afform/core/ang/af/afField.html index 6fb2f55f85..1d41d2cc13 100644 --- a/ext/afform/core/ang/af/afField.html +++ b/ext/afform/core/ang/af/afField.html @@ -1,6 +1,6 @@ -