Merge pull request #24115 from kcristiano/5.52-token
[civicrm-core.git] / ext / afform / core / ang / af / afField.component.js
index 60d41c0cdf8f476975fc63df3df1791f89f92251..aa83eac8fbae9dced69200437e697e5dc774f4c0 100644 (file)
     controller: function($scope, $element, crmApi4, $timeout, $location) {
       var ts = $scope.ts = CRM.ts('org.civicrm.afform'),
         ctrl = this,
+        // Prefix used for SearchKit explicit joins
+        namePrefix = '',
         boolOptions = [{id: true, label: ts('Yes')}, {id: false, label: ts('No')}],
+        // Used to store chain select options loaded on-the-fly
+        chainSelectOptions = null,
         // Only used for is_primary radio button
         noOptions = [{id: true, label: ''}];
 
@@ -29,6 +33,9 @@
 
         $element.addClass('af-field-type-' + _.kebabCase(ctrl.defn.input_type));
 
+        if (this.defn.name !== this.fieldName) {
+          namePrefix = this.fieldName.substr(0, this.fieldName.length - this.defn.name.length);
+        }
 
         if (ctrl.defn.search_range) {
           // Initialize value as object unless using relative date select
 
         // ChainSelect - watch control field & reload options as needed
         if (ctrl.defn.input_type === 'ChainSelect') {
-          $scope.$watch('dataProvider.getFieldData()[defn.input_attrs.control_field]', function(val) {
-            if (val) {
+          var controlField = namePrefix + ctrl.defn.input_attrs.control_field;
+          $scope.$watch('dataProvider.getFieldData()["' + controlField + '"]', function(val) {
+            // After switching option list, remove invalid options
+            function validateValue() {
+              var options = $scope.getOptions(),
+                value = $scope.dataProvider.getFieldData()[ctrl.fieldName];
+              if (_.isArray(value)) {
+                _.remove(value, function(item) {
+                  return !_.find(options, function(option) {return option.id == item;});
+                });
+              } else if (value && !_.find(options, function(option) {return option.id == value;})) {
+                $scope.dataProvider.getFieldData()[ctrl.fieldName] = '';
+              }
+            }
+            if (val && (typeof val === 'number' || val.length)) {
+              $('input[crm-ui-select]', $element).addClass('loading').prop('disabled', true);
               var params = {
-                where: [['name', '=', ctrl.fieldName]],
-                select: ['options'],
-                loadOptions: ['id', 'label'],
-                values: {}
+                name: ctrl.afFieldset.getFormName(),
+                modelName: ctrl.afFieldset.getName(),
+                fieldName: ctrl.fieldName,
+                joinEntity: ctrl.afJoin ? ctrl.afJoin.entity : null,
+                values: $scope.dataProvider.getFieldData()
               };
-              params.values[ctrl.defn.input_attrs.control_field] = val;
-              crmApi4($scope.dataProvider.getEntityType(), 'getFields', params, 0)
+              crmApi4('Afform', 'getOptions', params)
                 .then(function(data) {
-                  ctrl.defn.options = data.options;
+                  $('input[crm-ui-select]', $element).removeClass('loading').prop('disabled', !data.length);
+                  chainSelectOptions = data;
+                  validateValue();
                 });
+            } else {
+              chainSelectOptions = null;
+              validateValue();
             }
-          });
+          }, true);
         }
 
         // Wait for parent controllers to initialize
       // Params for the Afform.submitFile API when uploading a file field
       ctrl.getFileUploadParams = function() {
         return {
-          entityName: ctrl.afFieldset.modelName,
+          modelName: ctrl.afFieldset.getName(),
           fieldName: ctrl.fieldName,
           joinEntity: ctrl.afJoin ? ctrl.afJoin.entity : null,
           entityIndex: ctrl.getEntityIndex(),
       };
 
       $scope.getOptions = function () {
-        return ctrl.defn.options || (ctrl.fieldName === 'is_primary' && ctrl.defn.input_type === 'Radio' ? noOptions : boolOptions);
+        return chainSelectOptions || ctrl.defn.options || (ctrl.fieldName === 'is_primary' && ctrl.defn.input_type === 'Radio' ? noOptions : boolOptions);
       };
 
       $scope.select2Options = function() {