Skip to content

Commit 0a2b19d

Browse files
authored
Merge pull request #49 from QuickFlo/x-visible-when
x-visible-when
2 parents e7eea6e + 5d05d2a commit 0a2b19d

11 files changed

Lines changed: 679 additions & 19 deletions

File tree

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@ coverage
88
.vscode
99
.idea
1010
*.tsbuildinfo
11-
WARP.MD
11+
WARP.MD
12+
.envrc

docs/guide/examples/conditional-fields.md

Lines changed: 168 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,154 @@
11
# Conditional Fields Example
22

3-
Create dynamic forms where fields appear based on other field values using `oneOf`.
3+
Create dynamic forms where fields appear based on other field values.
44

5-
## Simple Conditional Example
5+
## Two Approaches
6+
7+
QuickForms offers two approaches for conditional fields:
8+
9+
| Approach | Best For |
10+
|----------|----------|
11+
| **`x-visible-when`** | Simple show/hide based on another field's value |
12+
| **`oneOf`/`anyOf`** | Complex scenarios with different validation rules per variant |
13+
14+
## Using `x-visible-when` (Recommended for Simple Cases)
15+
16+
For basic "show field X when field Y equals Z" scenarios, use `x-visible-when`:
17+
18+
```vue
19+
<script setup lang="ts">
20+
import { ref } from 'vue'
21+
import { DynamicForm } from '@quickflo/quickforms-vue'
22+
import type { JSONSchema } from '@quickflo/quickforms'
23+
24+
const schema: JSONSchema = {
25+
type: 'object',
26+
properties: {
27+
provider: {
28+
type: 'string',
29+
title: 'Cloud Provider',
30+
enum: ['aws', 'gcp', 'azure']
31+
},
32+
// Only visible when AWS is selected
33+
awsRegion: {
34+
type: 'string',
35+
title: 'AWS Region',
36+
enum: ['us-east-1', 'us-west-2', 'eu-west-1'],
37+
'x-visible-when': {
38+
field: 'provider',
39+
operator: 'eq',
40+
value: 'aws'
41+
}
42+
},
43+
// Only visible when GCP is selected
44+
gcpProject: {
45+
type: 'string',
46+
title: 'GCP Project ID',
47+
'x-visible-when': {
48+
field: 'provider',
49+
operator: 'eq',
50+
value: 'gcp'
51+
}
52+
},
53+
// Visible for multiple providers (AWS or GCP)
54+
enableEncryption: {
55+
type: 'boolean',
56+
title: 'Enable Encryption',
57+
'x-visible-when': {
58+
field: 'provider',
59+
operator: 'in',
60+
value: ['aws', 'gcp']
61+
}
62+
}
63+
}
64+
}
65+
66+
const formData = ref({ provider: 'aws' })
67+
</script>
68+
69+
<template>
70+
<DynamicForm :schema="schema" v-model="formData" />
71+
</template>
72+
```
73+
74+
### Supported Operators
75+
76+
| Operator | Aliases | Description | Example |
77+
|----------|---------|-------------|---------|
78+
| `eq` | `==`, `===` | Equals | `{ operator: 'eq', value: 'aws' }` |
79+
| `neq` | `!=`, `!==` | Not equals | `{ operator: 'neq', value: 'azure' }` |
80+
| `in` | | Value in array | `{ operator: 'in', value: ['aws', 'gcp'] }` |
81+
| `notIn` | `!in` | Value not in array | `{ operator: 'notIn', value: ['azure'] }` |
82+
| `truthy` | | Value is truthy | `{ operator: 'truthy' }` |
83+
| `falsy` | | Value is falsy | `{ operator: 'falsy' }` |
84+
| `gt` | `>` | Greater than | `{ operator: 'gt', value: 18 }` |
85+
| `gte` | `>=` | Greater than or equal | `{ operator: 'gte', value: 18 }` |
86+
| `lt` | `<` | Less than | `{ operator: 'lt', value: 100 }` |
87+
| `lte` | `<=` | Less than or equal | `{ operator: 'lte', value: 100 }` |
88+
| `like` | | Case-sensitive pattern | `{ operator: 'like', value: 'cloud-%' }` |
89+
| `ilike` | | Case-insensitive pattern | `{ operator: 'ilike', value: 'CLOUD-%' }` |
90+
91+
### Nested Field References
92+
93+
Reference fields in nested objects using dot notation:
94+
95+
```typescript
96+
{
97+
connectionConfig: {
98+
type: 'object',
99+
oneOf: [
100+
{ properties: { provider: { const: 'aws' } } },
101+
{ properties: { provider: { const: 'gcp' } } }
102+
]
103+
},
104+
// Reference nested field with dot notation
105+
awsSpecificOption: {
106+
type: 'string',
107+
'x-visible-when': {
108+
field: 'connectionConfig.provider',
109+
operator: 'eq',
110+
value: 'aws'
111+
}
112+
}
113+
}
114+
```
115+
116+
### Also: `x-readonly-when`
117+
118+
Make fields conditionally read-only using the same syntax:
119+
120+
```typescript
121+
{
122+
status: {
123+
type: 'string',
124+
enum: ['draft', 'published']
125+
},
126+
title: {
127+
type: 'string',
128+
// Readonly once published
129+
'x-readonly-when': {
130+
field: 'status',
131+
operator: 'eq',
132+
value: 'published'
133+
}
134+
}
135+
}
136+
```
137+
138+
**See:** [Schema Extensions - x-visible-when](/guide/schema-extensions#x-visible-when) for full documentation.
139+
140+
---
141+
142+
## Using `oneOf` (Advanced Approach)
143+
144+
For complex scenarios where you need:
145+
- Different validation rules per variant
146+
- Entirely different field sets with per-variant `required` arrays
147+
- Type-safe discriminated unions
148+
149+
Use `oneOf`:
150+
151+
## oneOf Example
6152

7153
```vue
8154
<script setup lang="ts">
@@ -362,8 +508,26 @@ const schema: JSONSchema = {
362508
}
363509
```
364510

511+
## Choosing the Right Approach
512+
513+
| Scenario | Recommended Approach |
514+
|----------|---------------------|
515+
| Show/hide a few fields based on a selection | `x-visible-when` |
516+
| Different required fields per variant | `oneOf` |
517+
| Same fields, just conditional visibility | `x-visible-when` |
518+
| Completely different form sections | `oneOf` |
519+
| Make fields readonly based on status | `x-readonly-when` |
520+
| Need tabs/dropdown UI for variant selection | `oneOf` with `x-oneof-style` |
521+
365522
## Tips
366523

524+
### For `x-visible-when`
525+
1. **Keep it simple**: Best for 1-3 conditional fields
526+
2. **Dot notation**: Reference nested fields with `parent.child` paths
527+
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.
529+
530+
### For `oneOf`
367531
1. **Clear Labels**: Use descriptive `title` in each `oneOf` schema
368532
2. **Default Values**: Set a default for the discriminator field
369533
3. **Enum Labels**: Use `x-enum-labels` for better UX
@@ -372,6 +536,6 @@ const schema: JSONSchema = {
372536

373537
## Next Steps
374538

375-
- [Custom Validation](/guide/guide/examples/custom-validation) - Add custom validation logic
539+
- [Schema Extensions - x-visible-when](/guide/schema-extensions#x-visible-when) - Full operator reference
540+
- [Custom Validation](/guide/examples/custom-validation) - Add custom validation logic
376541
- [Complex Types](/guide/complex-types) - More about oneOf, anyOf, allOf
377-
- [Schema Extensions](/guide/schema-extensions) - Custom schema properties

0 commit comments

Comments
 (0)