5.8 KiB
Conditional Logic Examples
This directory demonstrates all supported conditional operators in TypeDialog forms.
Overview
TypeDialog supports rich conditional logic for dynamic form behavior. Fields can be shown/hidden based on previous answers using the when attribute.
Running the Examples
CLI Backend
cargo run --bin typedialog -- examples/13-conditional-logic/conditional-demo.toml
TUI Backend
cargo run --bin typedialog-tui -- examples/13-conditional-logic/conditional-demo.toml
Web Backend
cargo run --bin typedialog-web -- examples/13-conditional-logic/conditional-demo.toml
Supported Operators
Comparison Operators
Equality and Inequality
==: Equal to!=: Not equal to
[[elements]]
name = "mysql_config"
when = "database_driver == mysql"
[[elements]]
name = "server_warning"
when = "database_driver != sqlite"
Numeric Comparisons
>: Greater than<: Less than>=: Greater than or equal<=: Less than or equal
[[elements]]
name = "privileged_port_warning"
when = "server_port < 1024"
[[elements]]
name = "high_port_warning"
when = "server_port > 10000"
String Operators
contains: Check if field contains substringstartswith: Check if field starts with prefixendswith: Check if field ends with suffix
[[elements]]
name = "https_notice"
when = "project_url startswith https"
[[elements]]
name = "github_specific"
when = "project_url endswith github.com"
[[elements]]
name = "gitlab_ci"
when = "project_url contains gitlab"
Array Membership
in: Check if value exists in array field
[[elements]]
name = "rust_toolchain"
when = "rust in detected_languages"
[[elements]]
name = "python_venv"
when = "python in detected_languages"
Works with:
- MultiSelect fields (JSON array or comma-separated string)
- Array values from JSON output
File System Conditions
file_exists(path): Check if file or directory exists!file_exists(path): Check if file does NOT exist (negation)
[[elements]]
name = "dockerfile_exists_notice"
when = "file_exists(Dockerfile)"
[[elements]]
name = "create_dockerfile"
when = "!file_exists(Dockerfile)"
[[elements]]
name = "env_setup"
type = "group"
includes = ["fragments/environment-setup.toml"]
when = "!file_exists(.env)"
Path resolution:
- Absolute paths:
/etc/config.toml - Relative paths:
Dockerfile,.env,config/settings.toml - Works with both files and directories
Form Flow Example
- Select database → Shows driver-specific fields
- Enter port number → Shows warnings based on port range
- Enter project URL → Shows platform-specific options
- Select languages → Shows language-specific tooling
- Check for files → Conditionally load setup fragments
Key Features
Dynamic Field Visibility
Fields appear/disappear based on user input:
# Only shows if user selects MySQL
[[elements]]
name = "mysql_password"
type = "password"
when = "database_driver == mysql"
Conditional Fragment Loading
Load entire form sections conditionally:
[[elements]]
name = "docker_setup"
type = "group"
includes = ["fragments/docker-init.toml"]
when = "!file_exists(Dockerfile)"
Multi-Condition Fields
Same field can have complex logic (future: && and ||):
# Current: Single condition per field
when = "rust in detected_languages"
# Future: Compound conditions
when = "(rust in detected_languages) && (server_port >= 1024)"
Testing Scenarios
Scenario 1: Database Configuration
- Select
mysql→ See MySQL-specific fields - Select
postgresql→ See PostgreSQL-specific fields - Select
sqlite→ No extra server fields
Scenario 2: Port Validation
- Enter
80→ See privileged port warning (< 1024) - Enter
8080→ See standard port notice (>= 1024) - Enter
15000→ See high port warning (> 10000)
Scenario 3: Language Detection
- Select
rust+python→ See both Rust and Python config fields - Select only
javascript→ See only Node.js version selector - Select none → No language-specific fields appear
Scenario 4: File System Checks
-
With Dockerfile present:
- Shows "Dockerfile found" notice
- Skips Docker setup wizard
-
Without Dockerfile:
- Asks to create Dockerfile
- Shows Docker setup group
-
With .env file:
- Asks to use existing config
- Skips environment setup
-
Without .env file:
- Loads environment setup fragment
- Prompts for all env variables
Implementation Details
Condition Evaluation
Conditions are evaluated at runtime during form execution:
- User answers a field
- System checks all pending fields for
whenconditions - Fields with satisfied conditions become visible
- Fields with unsatisfied conditions remain hidden
Fragment Loading
Conditional groups with includes load fragments only when condition is true:
[[elements]]
name = "advanced_config"
type = "group"
includes = ["fragments/advanced-settings.toml"]
when = "enable_advanced == true"
This prevents loading unnecessary form definitions until needed.
Type Conversion
TypeDialog automatically handles type conversions in conditions:
- String
"8080"compared to number1024→ converted to number - Boolean
truecompared to string"true"→ compared as boolean - Number compared to string number → compared numerically
Related Documentation
- Field Types Reference - All field types and attributes
- Fragment System - Dynamic form composition
- Nickel Integration - Schema-driven forms
Source Code
Condition evaluation logic: crates/typedialog-core/src/form_parser/conditions.rs