# 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 ```bash cargo run --bin typedialog -- examples/13-conditional-logic/conditional-demo.toml ``` ### TUI Backend ```bash cargo run --bin typedialog-tui -- examples/13-conditional-logic/conditional-demo.toml ``` ### Web Backend ```bash cargo run --bin typedialog-web -- examples/13-conditional-logic/conditional-demo.toml ``` ## Supported Operators ### Comparison Operators #### Equality and Inequality - `==`: Equal to - `!=`: Not equal to ```toml [[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 ```toml [[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 substring - `startswith`: Check if field starts with prefix - `endswith`: Check if field ends with suffix ```toml [[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 ```toml [[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) ```toml [[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 1. **Select database** → Shows driver-specific fields 2. **Enter port number** → Shows warnings based on port range 3. **Enter project URL** → Shows platform-specific options 4. **Select languages** → Shows language-specific tooling 5. **Check for files** → Conditionally load setup fragments ## Key Features ### Dynamic Field Visibility Fields appear/disappear based on user input: ```toml # Only shows if user selects MySQL [[elements]] name = "mysql_password" type = "password" when = "database_driver == mysql" ``` ### Conditional Fragment Loading Load entire form sections conditionally: ```toml [[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 `||`): ```toml # 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 1. Select `mysql` → See MySQL-specific fields 2. Select `postgresql` → See PostgreSQL-specific fields 3. Select `sqlite` → No extra server fields ### Scenario 2: Port Validation 1. Enter `80` → See privileged port warning (`< 1024`) 2. Enter `8080` → See standard port notice (`>= 1024`) 3. Enter `15000` → See high port warning (`> 10000`) ### Scenario 3: Language Detection 1. Select `rust` + `python` → See both Rust and Python config fields 2. Select only `javascript` → See only Node.js version selector 3. Select none → No language-specific fields appear ### Scenario 4: File System Checks 1. **With Dockerfile present**: - Shows "Dockerfile found" notice - Skips Docker setup wizard 2. **Without Dockerfile**: - Asks to create Dockerfile - Shows Docker setup group 3. **With .env file**: - Asks to use existing config - Skips environment setup 4. **Without .env file**: - Loads environment setup fragment - Prompts for all env variables ## Implementation Details ### Condition Evaluation Conditions are evaluated at runtime during form execution: 1. User answers a field 2. System checks all pending fields for `when` conditions 3. Fields with satisfied conditions become visible 4. Fields with unsatisfied conditions remain hidden ### Fragment Loading Conditional groups with `includes` load fragments only when condition is true: ```toml [[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 number `1024` → converted to number - Boolean `true` compared to string `"true"` → compared as boolean - Number compared to string number → compared numerically ## Related Documentation - [Field Types Reference](../../docs/field_types.md) - All field types and attributes - [Fragment System](../../docs/fragment-search-paths.md) - Dynamic form composition - [Nickel Integration](../../docs/nickel.md) - Schema-driven forms ## Source Code Condition evaluation logic: `crates/typedialog-core/src/form_parser/conditions.rs`