Skip to content

Commit 5d05d2a

Browse files
committed
```
feat: add automatic value clearing for conditional fields - Add x-clear-on-hide schema extension to control value clearing behavior - Implement setFieldValue method in FormContext for internal field updates - Auto-clear field values when hidden via x-visible-when (defaults to true) - Add watcher in FieldRenderer to clear values on visibility changes - Update documentation for conditional fields and schema extensions ```
1 parent 4549d48 commit 5d05d2a

5 files changed

Lines changed: 99 additions & 1 deletion

File tree

docs/guide/examples/conditional-fields.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -525,6 +525,7 @@ const schema: JSONSchema = {
525525
1. **Keep it simple**: Best for 1-3 conditional fields
526526
2. **Dot notation**: Reference nested fields with `parent.child` paths
527527
3. **Combine with `x-readonly-when`**: Show a field but make it readonly based on conditions
528+
4. **Values auto-clear**: When a field becomes hidden, its value is automatically cleared. Use `'x-clear-on-hide': false` to preserve values.
528529

529530
### For `oneOf`
530531
1. **Clear Labels**: Use descriptive `title` in each `oneOf` schema

docs/guide/schema-extensions.md

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,60 @@ You can reference fields nested within objects using dot notation:
147147

148148
---
149149

150+
## `x-clear-on-hide`
151+
152+
**Purpose:** Control whether a field's value is cleared when it becomes hidden via `x-visible-when`
153+
154+
**Type:** `boolean`
155+
156+
**Default Behavior:** Fields with `x-visible-when` automatically clear their values when hidden. Use `x-clear-on-hide: false` to preserve values.
157+
158+
**Example:**
159+
```typescript
160+
{
161+
accountType: {
162+
type: 'string',
163+
enum: ['personal', 'business']
164+
},
165+
// Value is cleared when accountType changes away from 'business'
166+
taxId: {
167+
type: 'string',
168+
title: 'Tax ID',
169+
'x-visible-when': {
170+
field: 'accountType',
171+
operator: 'eq',
172+
value: 'business'
173+
}
174+
// x-clear-on-hide defaults to true when x-visible-when is present
175+
},
176+
// Value is preserved even when hidden
177+
internalNotes: {
178+
type: 'string',
179+
'x-visible-when': {
180+
field: 'accountType',
181+
operator: 'eq',
182+
value: 'business'
183+
},
184+
'x-clear-on-hide': false // Preserve value when hidden
185+
}
186+
}
187+
```
188+
189+
**Use Cases:**
190+
- Clear provider-specific settings when switching providers
191+
- Preserve user input that shouldn't be lost on visibility changes
192+
- Ensure stale data isn't submitted for hidden fields
193+
194+
**Why clear by default?**
195+
When fields become hidden, their values typically become irrelevant. Clearing them:
196+
- Prevents stale data from being submitted
197+
- Ensures the form model matches the visible UI
198+
- Avoids confusion when switching between options
199+
200+
**Note:** This only affects fields hidden via `x-visible-when`. Fields hidden with `x-hidden` or `x-roles` are not affected.
201+
202+
---
203+
150204
## `x-hidden`
151205

152206
**Purpose:** Completely hide a field from rendering (unconditionally)

packages/vue/src/components/DynamicForm.vue

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,18 @@ const formContext = reactive({
163163
return getNestedValue(formVals, path) as T | undefined;
164164
});
165165
},
166+
/**
167+
* Set a field value by path.
168+
* Supports dot notation for nested paths.
169+
*/
170+
setFieldValue: (path: string, value: unknown) => {
171+
if (isSingleField.value) {
172+
// For single-field schemas, we need to update the nested path within the root field
173+
setFieldValue(`${SINGLE_FIELD_PATH}.${path}`, value);
174+
} else {
175+
setFieldValue(path, value);
176+
}
177+
},
166178
/**
167179
* Watch all form values and call callback when they change.
168180
* Returns a stop function to unsubscribe.

packages/vue/src/components/FieldRenderer.vue

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<script setup lang="ts">
2-
import { computed } from 'vue';
2+
import { computed, watch } from 'vue';
33
import type { JSONSchema, UISchemaElement } from '@quickflo/quickforms';
44
import { useFormContext } from '../composables/useFormContext.js';
55
@@ -143,6 +143,27 @@ const visibleWhenResult = computed(() => {
143143
return evaluateCondition(condition, visibleWhenFieldValue.value);
144144
});
145145
146+
// Check if field should clear its value when hidden
147+
// Defaults to true for x-visible-when fields, but can be overridden with x-clear-on-hide: false
148+
const shouldClearOnHide = computed(() => {
149+
const schema = props.schema as any;
150+
// If explicitly set, use that value
151+
if (schema['x-clear-on-hide'] !== undefined) {
152+
return schema['x-clear-on-hide'] === true;
153+
}
154+
// Default: clear on hide only if x-visible-when is configured
155+
return visibleWhenConfig.value !== undefined;
156+
});
157+
158+
// Watch visibility changes and clear value when field becomes hidden
159+
watch(visibleWhenResult, (isNowVisible, wasVisible) => {
160+
// Only clear when transitioning from visible to hidden
161+
if (wasVisible === true && isNowVisible === false && shouldClearOnHide.value) {
162+
// Clear the field value
163+
context.setFieldValue(props.path, undefined);
164+
}
165+
});
166+
146167
// Get reactive field value for x-readonly-when condition
147168
const readonlyWhenConfig = computed(() => {
148169
const schema = props.schema as any;

packages/vue/src/types/index.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,16 @@ export interface FormContext {
201201
* ```
202202
*/
203203
useFieldValue: <T = unknown>(path: string) => ComputedRef<T | undefined>;
204+
/**
205+
* Set a field value by path. Used internally by FieldRenderer to clear
206+
* values when fields become hidden via x-visible-when.
207+
*
208+
* @example
209+
* ```ts
210+
* formContext.setFieldValue('provider.model', undefined);
211+
* ```
212+
*/
213+
setFieldValue: (path: string, value: unknown) => void;
204214
/**
205215
* Watch form values and call callback when they change.
206216
* Returns a stop function to unsubscribe.

0 commit comments

Comments
 (0)