Ver Fonte

adding otion to hide form form data depending on vars

Medowar há 1 mês atrás
pai
commit
973c627421
2 ficheiros alterados com 107 adições e 6 exclusões
  1. 76 4
      assets/js/form.js
  2. 31 2
      src/Form/Validator.php

+ 76 - 4
assets/js/form.js

@@ -407,6 +407,76 @@
     return evaluateFieldRule(field.visible_if, formData);
   }
 
+  function isOptionVisible(option, formData) {
+    if (!option || typeof option !== 'object') {
+      return true;
+    }
+
+    if (option.visible_if && typeof option.visible_if === 'object' && !evaluateFieldRule(option.visible_if, formData)) {
+      return false;
+    }
+
+    if (option.hidden_if && typeof option.hidden_if === 'object' && evaluateFieldRule(option.hidden_if, formData)) {
+      return false;
+    }
+
+    return true;
+  }
+
+  function applySelectOptionVisibility(formData) {
+    let changedSelection = false;
+
+    fieldsByKey.forEach((field, key) => {
+      if (!field || typeof field !== 'object') {
+        return;
+      }
+
+      if (String(field.type || '') !== 'select' || !Array.isArray(field.options)) {
+        return;
+      }
+
+      const select = applicationForm.querySelector('[name="form_data[' + key + ']"]');
+      if (!select) {
+        return;
+      }
+
+      const optionRules = new Map();
+      field.options.forEach((option) => {
+        if (!option || typeof option !== 'object') {
+          return;
+        }
+
+        optionRules.set(String(option.value || ''), option);
+      });
+
+      let selectedHidden = false;
+      Array.from(select.options).forEach((optionEl) => {
+        const optionValue = String(optionEl.value || '');
+        if (optionValue === '') {
+          optionEl.hidden = false;
+          optionEl.disabled = false;
+          return;
+        }
+
+        const optionRule = optionRules.get(optionValue);
+        const visible = isOptionVisible(optionRule, formData);
+        optionEl.hidden = !visible;
+        optionEl.disabled = !visible;
+
+        if (!visible && optionEl.selected) {
+          selectedHidden = true;
+        }
+      });
+
+      if (selectedHidden) {
+        select.value = '';
+        changedSelection = true;
+      }
+    });
+
+    return changedSelection;
+  }
+
   function hasFileValue(fieldKey) {
     const fileInput = applicationForm.querySelector('[name="' + fieldKey + '"]');
     const cameraInput = applicationForm.querySelector('[name="' + fieldKey + '__camera"]');
@@ -442,6 +512,8 @@
 
   function applyFieldVisibility() {
     const formData = collectCurrentFormData();
+    const changedSelection = applySelectOptionVisibility(formData);
+    const effectiveFormData = changedSelection ? collectCurrentFormData() : formData;
 
     fieldsByKey.forEach((field, key) => {
       const container = fieldContainersByKey.get(key);
@@ -449,7 +521,7 @@
         return;
       }
 
-      const visible = isFieldVisible(field, formData);
+      const visible = isFieldVisible(field, effectiveFormData);
       container.classList.toggle('field-hidden-by-rule', !visible);
 
       const controlElements = container.querySelectorAll('input, select, textarea');
@@ -799,12 +871,12 @@
     const fileInput = applicationForm.querySelector('[name="' + fieldKey + '"]');
     const cameraInput = applicationForm.querySelector('[name="' + fieldKey + '__camera"]');
 
-    let label = 'Keine Datei gewählt';
+    let label = 'Noch keine Datei hochgeladen';
     if (fileInput && fileInput.files && fileInput.files[0]) {
-      label = 'Ausgewählt: ' + fileInput.files[0].name;
+      label = 'Datei ausgewählt: ' + fileInput.files[0].name;
     }
     if (cameraInput && cameraInput.files && cameraInput.files[0]) {
-      label = 'Ausgewählt: ' + cameraInput.files[0].name + ' (Foto)';
+      label = 'Foto ausgewählt: ' + cameraInput.files[0].name;
     }
 
     target.textContent = label;

+ 31 - 2
src/Form/Validator.php

@@ -55,8 +55,23 @@ final class Validator
             }
 
             if ($type === 'select' && isset($field['options']) && is_array($field['options'])) {
-                $allowed = array_map(static fn ($item): string => (string) ($item['value'] ?? ''), $field['options']);
-                if (!in_array((string) $value, $allowed, true)) {
+                $selected = (string) $value;
+                $validSelection = false;
+
+                foreach ($field['options'] as $option) {
+                    if (!is_array($option)) {
+                        continue;
+                    }
+
+                    if ((string) ($option['value'] ?? '') !== $selected) {
+                        continue;
+                    }
+
+                    $validSelection = $this->isOptionVisible($option, $data);
+                    break;
+                }
+
+                if (!$validSelection) {
                     $errors[$key] = 'Ungültige Auswahl.';
                 }
             }
@@ -162,6 +177,20 @@ final class Validator
         return $age >= 18;
     }
 
+    /** @param array<string, mixed> $option */
+    private function isOptionVisible(array $option, array $data): bool
+    {
+        if (isset($option['visible_if']) && is_array($option['visible_if']) && !$this->ruleMatches($option['visible_if'], $data)) {
+            return false;
+        }
+
+        if (isset($option['hidden_if']) && is_array($option['hidden_if']) && $this->ruleMatches($option['hidden_if'], $data)) {
+            return false;
+        }
+
+        return true;
+    }
+
     private function isEmptyValue(mixed $value, string $type): bool
     {
         if ($type === 'checkbox') {