Enhance form logic property resolver and validation UI
- Refactor `shouldBeRequired()` method in FormLogicPropertyResolver for clearer logic and better handling of conditional requirements - Add comprehensive test cases for dynamic field requirement logic - Update CustomFieldValidation component with improved UI and guidance for validation setup - Improve error message and validation rule description in form validation interface
This commit is contained in:
parent
f5b9b86c16
commit
853760484c
|
|
@ -29,22 +29,28 @@ class FormLogicPropertyResolver
|
||||||
|
|
||||||
public function shouldBeRequired(): bool
|
public function shouldBeRequired(): bool
|
||||||
{
|
{
|
||||||
if (! isset($this->property['required'])) {
|
// Default required to false if not set
|
||||||
return false;
|
$isRequired = $this->property['required'] ?? false;
|
||||||
}
|
|
||||||
|
|
||||||
if (! $this->logic) {
|
if (! $this->logic) {
|
||||||
return $this->property['required'];
|
return $isRequired;
|
||||||
}
|
}
|
||||||
|
|
||||||
$conditionsMet = FormLogicConditionChecker::conditionsMet($this->logic['conditions'], $this->formData);
|
$conditionsMet = FormLogicConditionChecker::conditionsMet($this->logic['conditions'], $this->formData);
|
||||||
if ($conditionsMet && $this->property['required'] && count($this->logic['actions']) > 0 && (in_array('make-it-optional', $this->logic['actions']) || in_array('hide-block', $this->logic['actions']))) {
|
|
||||||
return false;
|
// If conditions are met and we have actions
|
||||||
} elseif ($conditionsMet && ! $this->property['required'] && count($this->logic['actions']) > 0 && in_array('require-answer', $this->logic['actions'])) {
|
if ($conditionsMet && !empty($this->logic['actions'])) {
|
||||||
return true;
|
// If field is required but should be made optional
|
||||||
} else {
|
if ($isRequired && (in_array('make-it-optional', $this->logic['actions']) || in_array('hide-block', $this->logic['actions']))) {
|
||||||
return $this->property['required'];
|
return false;
|
||||||
|
}
|
||||||
|
// If field is not required but should be required
|
||||||
|
if (!$isRequired && in_array('require-answer', $this->logic['actions'])) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return $isRequired;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function shouldBeHidden(): bool
|
public function shouldBeHidden(): bool
|
||||||
|
|
|
||||||
|
|
@ -107,4 +107,91 @@ it('can validate form logic property resolver', function ($property, $formData,
|
||||||
['93ea3198-353f-440b-8dc9-2ac9a7bee124' => [], '93ea3198-353f-440b-8dc9-2ac9a7bee222' => ['abc']],
|
['93ea3198-353f-440b-8dc9-2ac9a7bee124' => [], '93ea3198-353f-440b-8dc9-2ac9a7bee222' => ['abc']],
|
||||||
false,
|
false,
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
[
|
||||||
|
'id' => 'text_field',
|
||||||
|
'name' => 'Required if checked',
|
||||||
|
'type' => 'text',
|
||||||
|
'hidden' => false,
|
||||||
|
'logic' => [
|
||||||
|
'conditions' => [
|
||||||
|
'operatorIdentifier' => 'and',
|
||||||
|
'children' => [
|
||||||
|
[
|
||||||
|
'identifier' => 'checkbox',
|
||||||
|
'value' => [
|
||||||
|
'operator' => 'is_checked',
|
||||||
|
'property_meta' => [
|
||||||
|
'id' => 'checkbox_field',
|
||||||
|
'type' => 'checkbox'
|
||||||
|
],
|
||||||
|
'value' => true
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
],
|
||||||
|
'actions' => ['require-answer']
|
||||||
|
]
|
||||||
|
],
|
||||||
|
['checkbox_field' => true],
|
||||||
|
true
|
||||||
|
],
|
||||||
|
[
|
||||||
|
[
|
||||||
|
'id' => 'text_field',
|
||||||
|
'name' => 'Required if checked',
|
||||||
|
'type' => 'text',
|
||||||
|
'hidden' => false,
|
||||||
|
'logic' => [
|
||||||
|
'conditions' => [
|
||||||
|
'operatorIdentifier' => 'and',
|
||||||
|
'children' => [
|
||||||
|
[
|
||||||
|
'identifier' => 'checkbox',
|
||||||
|
'value' => [
|
||||||
|
'operator' => 'is_checked',
|
||||||
|
'property_meta' => [
|
||||||
|
'id' => 'checkbox_field',
|
||||||
|
'type' => 'checkbox'
|
||||||
|
],
|
||||||
|
'value' => true
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
],
|
||||||
|
'actions' => ['require-answer']
|
||||||
|
]
|
||||||
|
],
|
||||||
|
['checkbox_field' => false],
|
||||||
|
false
|
||||||
|
],
|
||||||
|
[
|
||||||
|
[
|
||||||
|
'id' => 'text_field',
|
||||||
|
'name' => 'Required if checked',
|
||||||
|
'type' => 'text',
|
||||||
|
'hidden' => false,
|
||||||
|
'logic' => [
|
||||||
|
'conditions' => [
|
||||||
|
'operatorIdentifier' => 'and',
|
||||||
|
'children' => [
|
||||||
|
[
|
||||||
|
'identifier' => 'checkbox',
|
||||||
|
'value' => [
|
||||||
|
'operator' => 'is_checked',
|
||||||
|
'property_meta' => [
|
||||||
|
'id' => 'checkbox_field',
|
||||||
|
'type' => 'checkbox'
|
||||||
|
],
|
||||||
|
'value' => true
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
],
|
||||||
|
'actions' => ['require-answer']
|
||||||
|
]
|
||||||
|
],
|
||||||
|
['checkbox_field' => null],
|
||||||
|
false
|
||||||
|
]
|
||||||
]);
|
]);
|
||||||
|
|
|
||||||
|
|
@ -1,33 +1,51 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="py-2 px-4">
|
<div class="py-2 px-4">
|
||||||
<p class="text-gray-500 text-xs mb-3">
|
<div class="space-y-4">
|
||||||
Add some custom validation. Save your form before testing.
|
<!-- Step 1: Validation Rules -->
|
||||||
</p>
|
<div>
|
||||||
|
<h3 class="font-medium text-gray-900 text-sm mb-1">
|
||||||
<div class="py-2">
|
Step 1: Set Validation Rules
|
||||||
<p class="font-semibold text-sm text-gray-700">
|
</h3>
|
||||||
Validation criteria for field acceptance
|
<p class="text-gray-500 text-xs mb-3">
|
||||||
</p>
|
Define <span class="font-semibold">conditions that must be met</span> for this field to be valid. If these conditions are not met, the field will be marked as invalid.
|
||||||
<condition-editor
|
</p>
|
||||||
ref="filter-editor"
|
<condition-editor
|
||||||
v-model="validation.conditions"
|
ref="filter-editor"
|
||||||
class="mt-1 border-t border rounded-md mb-3"
|
v-model="validation.conditions"
|
||||||
:form="form"
|
class="mt-1 border-t border rounded-md"
|
||||||
/>
|
:form="form"
|
||||||
<text-input
|
/>
|
||||||
name="error_message"
|
</div>
|
||||||
class=""
|
|
||||||
:form="field.validation"
|
<!-- Step 2: Error Message -->
|
||||||
label="Error message"
|
<div>
|
||||||
help="Displayed when the validation fails"
|
<h3 class="font-medium text-gray-900 text-sm mb-1">
|
||||||
|
Step 2: Set Error Message
|
||||||
|
</h3>
|
||||||
|
<p class="text-gray-500 text-xs mb-2">
|
||||||
|
Enter the message that will be <span class="font-semibold">shown to users when the validation rules above are not met</span>.
|
||||||
|
</p>
|
||||||
|
<text-input
|
||||||
|
name="error_message"
|
||||||
|
:form="field.validation"
|
||||||
|
label="Error message"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<UAlert
|
||||||
|
icon="i-heroicons-information-circle"
|
||||||
|
color="yellow"
|
||||||
|
variant="subtle"
|
||||||
|
size="sm"
|
||||||
|
description="Remember to save your form to apply these validation rules."
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import ConditionEditor from "./form-logic-components/ConditionEditor.client.vue"
|
|
||||||
import { default as _has } from "lodash/has"
|
import { default as _has } from "lodash/has"
|
||||||
|
import ConditionEditor from "./form-logic-components/ConditionEditor.client.vue"
|
||||||
export default {
|
export default {
|
||||||
name: 'FormValidation',
|
name: 'FormValidation',
|
||||||
components: {ConditionEditor},
|
components: {ConditionEditor},
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue