Afform - Fix display of boolean checkboxes
authorcolemanw <coleman@civicrm.org>
Sat, 23 Sep 2023 02:39:21 +0000 (22:39 -0400)
committercolemanw <coleman@civicrm.org>
Sat, 23 Sep 2023 02:44:19 +0000 (22:44 -0400)
ext/afform/admin/ang/afGuiEditor/elements/afGuiField.component.js
ext/afform/admin/ang/afGuiEditor/inputType/CheckBox.html
ext/afform/core/Civi/Afform/AfformMetadataInjector.php
ext/afform/core/ang/af/afField.component.js

index a6124cde53c5a4e3349605cfa0893a58a90e1faf..8772532e281a59f917395ef27528d029e4faaea0 100644 (file)
 
       $scope.hasOptions = function() {
         var inputType = $scope.getProp('input_type');
-        return _.contains(['CheckBox', 'Radio', 'Select'], inputType) && !(inputType === 'CheckBox' && !ctrl.getDefn().options);
+        return _.contains(['CheckBox', 'Radio', 'Select'], inputType) && !(inputType === 'CheckBox' && ctrl.getDefn().data_type === 'Boolean');
       };
 
       this.getOptions = function() {
           }
           return entityRefOptions;
         }
-        return ctrl.getDefn().options || ($scope.getProp('input_type') === 'CheckBox' ? null : yesNo);
+        return ctrl.getDefn().options || (ctrl.getDefn().data_type === 'Boolean' ? yesNo : null);
       };
 
       $scope.resetOptions = function() {
               delete ctrl.node.defn.input_attrs.multiple;
               clearOut(ctrl.node, ['defn', 'input_attrs']);
             }
+            // Boolean checkbox has no options
+            if (val === 'CheckBox' && ctrl.getDefn().data_type === 'Boolean' && ctrl.node.defn) {
+              delete ctrl.node.defn.options;
+            }
           }
           setFieldDefn();
 
index 1e6762315d2729443850fb572128ba2c6b6930d5..d5d704b2a91f739ae1550ce62930514e074dedf9 100644 (file)
@@ -1,7 +1,7 @@
-<ul class="crm-checkbox-list" ng-if="$ctrl.getOptions()" title="{{:: ts('Set default value') }}">
+<ul class="crm-checkbox-list" ng-if="$ctrl.getDefn().data_type !== 'Boolean'" title="{{:: ts('Set default value') }}">
   <li ng-repeat="opt in $ctrl.getOptions()" >
     <input type="checkbox" ng-checked="defaultValueContains(opt.id)" ng-click="toggleDefaultValueItem(opt.id)" >
     <label>{{ opt.label }}</label>
   </li>
 </ul>
-<input type="checkbox" ng-if="!$ctrl.getOptions()" ng-checked="defaultValueContains('1')" ng-click="toggleDefaultValueItem('1') ">
+<input type="checkbox" ng-if="$ctrl.getDefn().data_type === 'Boolean'" ng-checked="defaultValueContains('1')" ng-click="toggleDefaultValueItem('1') ">
index 2aa4dbac14614989fc26aa0b813170adc816c606..0ff0c16e6b1cd0cea8eaf04a4aa5ad7e8fed39a4 100644 (file)
@@ -161,6 +161,11 @@ class AfformMetadataInjector {
       }
     }
 
+    // Boolean checkbox has no options
+    if ($fieldInfo['data_type'] === 'Boolean' && $inputType === 'CheckBox') {
+      unset($fieldInfo['options'], $fieldDefn['options']);
+    }
+
     foreach ($fieldInfo as $name => $prop) {
       // Merge array props 1 level deep
       if (in_array($name, $deep) && !empty($fieldDefn[$name])) {
index c8646f718c08cb50440df5f8c73657e2fcedbd0e..14aa81122c593c630adfecd59730c9019825c960 100644 (file)
           this.search_operator = this.defn.search_operator;
         }
 
+        // Ensure boolean options are truly boolean
+        if (this.defn.data_type === 'Boolean' && this.defn.options) {
+          this.defn.options.forEach((option) => option.id = !!option.id);
+        }
+
         // 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) {
       this.isMultiple = function() {
         return (
           (['Select', 'EntityRef', 'ChainSelect'].includes(ctrl.defn.input_type) && ctrl.defn.input_attrs.multiple) ||
-          (ctrl.defn.input_type === 'CheckBox' && ctrl.defn.options)
+          (ctrl.defn.input_type === 'CheckBox' && ctrl.defn.data_type !== 'Boolean')
         );
       };