# Property Dependencies Guide Deep dive into n8n property dependencies and displayOptions mechanism. --- ## What Are Property Dependencies? **Definition**: Rules that control when fields are visible or required based on other field values. **Mechanism**: `displayOptions` in node schema **Purpose**: - Show relevant fields only - Hide irrelevant fields - Simplify configuration UX - Prevent invalid configurations --- ## displayOptions Structure ### Basic Format ```javascript { "name": "fieldName", "type": "string", "displayOptions": { "show": { "otherField": ["value1", "value2"] } } } ``` **Translation**: Show `fieldName` when `otherField` equals "value1" OR "value2" ### Show vs Hide #### show (Most Common) **Show field when condition matches**: ```javascript { "name": "body", "displayOptions": { "show": { "sendBody": [true] } } } ``` **Meaning**: Show `body` when `sendBody = true` #### hide (Less Common) **Hide field when condition matches**: ```javascript { "name": "advanced", "displayOptions": { "hide": { "simpleMode": [true] } } } ``` **Meaning**: Hide `advanced` when `simpleMode = true` ### Multiple Conditions (AND Logic) ```javascript { "name": "body", "displayOptions": { "show": { "sendBody": [true], "method": ["POST", "PUT", "PATCH"] } } } ``` **Meaning**: Show `body` when: - `sendBody = true` AND - `method IN (POST, PUT, PATCH)` **All conditions must match** (AND logic) ### Multiple Values (OR Logic) ```javascript { "name": "someField", "displayOptions": { "show": { "method": ["POST", "PUT", "PATCH"] } } } ``` **Meaning**: Show `someField` when: - `method = POST` OR - `method = PUT` OR - `method = PATCH` **Any value matches** (OR logic) --- ## Common Dependency Patterns ### Pattern 1: Boolean Toggle **Use case**: Optional feature flag **Example**: HTTP Request sendBody ```javascript // Field: sendBody (boolean) { "name": "sendBody", "type": "boolean", "default": false } // Field: body (depends on sendBody) { "name": "body", "displayOptions": { "show": { "sendBody": [true] } } } ``` **Flow**: 1. User sees sendBody checkbox 2. When checked → body field appears 3. When unchecked → body field hides ### Pattern 2: Resource/Operation Cascade **Use case**: Different operations show different fields **Example**: Slack message operations ```javascript // Operation: post { "name": "channel", "displayOptions": { "show": { "resource": ["message"], "operation": ["post"] } } } // Operation: update { "name": "messageId", "displayOptions": { "show": { "resource": ["message"], "operation": ["update"] } } } ``` **Flow**: 1. User selects resource="message" 2. User selects operation="post" → sees channel 3. User changes to operation="update" → channel hides, messageId shows ### Pattern 3: Type-Specific Configuration **Use case**: Different types need different fields **Example**: IF node conditions ```javascript // String operations { "name": "value2", "displayOptions": { "show": { "conditions.string.0.operation": ["equals", "notEquals", "contains"] } } } // Unary operations (isEmpty) don't show value2 { "displayOptions": { "hide": { "conditions.string.0.operation": ["isEmpty", "isNotEmpty"] } } } ``` ### Pattern 4: Method-Specific Fields **Use case**: HTTP methods have different options **Example**: HTTP Request ```javascript // Query parameters (all methods can have) { "name": "queryParameters", "displayOptions": { "show": { "sendQuery": [true] } } } // Body (only certain methods) { "name": "body", "displayOptions": { "show": { "sendBody": [true], "method": ["POST", "PUT", "PATCH", "DELETE"] } } } ``` --- ## Using get_property_dependencies ### Basic Usage ```javascript const deps = get_property_dependencies({ nodeType: "nodes-base.httpRequest" }); ``` ### Example Response ```javascript { "nodeType": "n8n-nodes-base.httpRequest", "dependencies": { "body": { "shows_when": { "sendBody": [true], "method": ["POST", "PUT", "PATCH", "DELETE"] }, "required_when_shown": true }, "queryParameters": { "shows_when": { "sendQuery": [true] }, "required_when_shown": false }, "headerParameters": { "shows_when": { "sendHeaders": [true] }, "required_when_shown": false } } } ``` ### When to Use **✅ Use when**: - Validation fails with "missing field" but you don't see that field - A field appears/disappears unexpectedly - You need to understand what controls field visibility - Building dynamic configuration tools **❌ Don't use when**: - Simple configuration (use get_node_essentials) - Just starting configuration - Field requirements are obvious --- ## Complex Dependency Examples ### Example 1: HTTP Request Complete Flow **Scenario**: Configuring POST with JSON body **Step 1**: Set method ```javascript { "method": "POST" // → sendBody becomes visible } ``` **Step 2**: Enable body ```javascript { "method": "POST", "sendBody": true // → body field becomes visible AND required } ``` **Step 3**: Configure body ```javascript { "method": "POST", "sendBody": true, "body": { "contentType": "json" // → content field becomes visible AND required } } ``` **Step 4**: Add content ```javascript { "method": "POST", "sendBody": true, "body": { "contentType": "json", "content": { "name": "John", "email": "john@example.com" } } } // ✅ Valid! ``` **Dependency chain**: ``` method=POST → sendBody visible → sendBody=true → body visible + required → body.contentType=json → body.content visible + required ``` ### Example 2: IF Node Operator Dependencies **Scenario**: String comparison with different operators **Binary operator** (equals): ```javascript { "conditions": { "string": [ { "operation": "equals" // → value1 required // → value2 required // → singleValue should NOT be set } ] } } ``` **Unary operator** (isEmpty): ```javascript { "conditions": { "string": [ { "operation": "isEmpty" // → value1 required // → value2 should NOT be set // → singleValue should be true (auto-added) } ] } } ``` **Dependency table**: | Operator | value1 | value2 | singleValue | |---|---|---|---| | equals | Required | Required | false | | notEquals | Required | Required | false | | contains | Required | Required | false | | isEmpty | Required | Hidden | true | | isNotEmpty | Required | Hidden | true | ### Example 3: Slack Operation Matrix **Scenario**: Different Slack operations show different fields ```javascript // post message { "resource": "message", "operation": "post" // Shows: channel (required), text (required), attachments, blocks } // update message { "resource": "message", "operation": "update" // Shows: messageId (required), text (required), channel (optional) } // delete message { "resource": "message", "operation": "delete" // Shows: messageId (required), channel (required) // Hides: text, attachments, blocks } // get message { "resource": "message", "operation": "get" // Shows: messageId (required), channel (required) // Hides: text, attachments, blocks } ``` **Field visibility matrix**: | Field | post | update | delete | get | |---|---|---|---|---| | channel | Required | Optional | Required | Required | | text | Required | Required | Hidden | Hidden | | messageId | Hidden | Required | Required | Required | | attachments | Optional | Optional | Hidden | Hidden | | blocks | Optional | Optional | Hidden | Hidden | --- ## Nested Dependencies ### What Are They? **Definition**: Dependencies within object properties **Example**: HTTP Request body.contentType controls body.content structure ```javascript { "body": { "contentType": "json", // → content expects JSON object "content": { "key": "value" } } } { "body": { "contentType": "form-data", // → content expects form fields array "content": [ { "name": "field1", "value": "value1" } ] } } ``` ### How to Handle **Strategy**: Configure parent first, then children ```javascript // Step 1: Parent { "body": { "contentType": "json" // Set parent first } } // Step 2: Children (structure determined by parent) { "body": { "contentType": "json", "content": { // JSON object format "key": "value" } } } ``` --- ## Auto-Sanitization and Dependencies ### What Auto-Sanitization Fixes **Operator structure issues** (IF/Switch nodes): **Example**: singleValue property ```javascript // You configure (missing singleValue) { "type": "boolean", "operation": "isEmpty" // Missing singleValue } // Auto-sanitization adds it { "type": "boolean", "operation": "isEmpty", "singleValue": true // ✅ Added automatically } ``` ### What It Doesn't Fix **Missing required fields**: ```javascript // You configure (missing channel) { "resource": "message", "operation": "post", "text": "Hello" // Missing required field: channel } // Auto-sanitization does NOT add // You must add it yourself { "resource": "message", "operation": "post", "channel": "#general", // ← You must add "text": "Hello" } ``` --- ## Troubleshooting Dependencies ### Problem 1: "Field X is required but not visible" **Error**: ```json { "type": "missing_required", "property": "body", "message": "body is required" } ``` **But you don't see body field in configuration!** **Solution**: ```javascript // Check dependencies const deps = get_property_dependencies({ nodeType: "nodes-base.httpRequest" }); // Find that body shows when sendBody=true // Add sendBody { "method": "POST", "sendBody": true, // ← Now body appears! "body": {...} } ``` ### Problem 2: "Field disappears when I change operation" **Scenario**: ```javascript // Working configuration { "resource": "message", "operation": "post", "channel": "#general", "text": "Hello" } // Change operation { "resource": "message", "operation": "update", // Changed "channel": "#general", // Still here "text": "Updated" // Still here // Missing: messageId (required for update!) } ``` **Validation error**: "messageId is required" **Why**: Different operation = different required fields **Solution**: ```javascript // Check essentials for new operation get_node_essentials({ nodeType: "nodes-base.slack" }); // Configure for update operation { "resource": "message", "operation": "update", "messageId": "1234567890", // Required for update "text": "Updated", "channel": "#general" // Optional for update } ``` ### Problem 3: "Validation passes but field doesn't save" **Scenario**: Field hidden by dependencies after validation **Example**: ```javascript // Configure { "method": "GET", "sendBody": true, // ❌ GET doesn't support body "body": {...} // This will be stripped } // After save { "method": "GET" // body removed because method=GET hides it } ``` **Solution**: Respect dependencies from the start ```javascript // Correct approach get_property_dependencies({ nodeType: "nodes-base.httpRequest" }); // See that body only shows for POST/PUT/PATCH/DELETE // Use correct method { "method": "POST", "sendBody": true, "body": {...} } ``` --- ## Advanced Patterns ### Pattern 1: Conditional Required with Fallback **Example**: Channel can be string OR expression ```javascript // Option 1: String { "channel": "#general" } // Option 2: Expression { "channel": "={{$json.channelName}}" } // Validation accepts both ``` ### Pattern 2: Mutually Exclusive Fields **Example**: Use either ID or name, not both ```javascript // Use messageId { "messageId": "1234567890" // name not needed } // OR use messageName { "messageName": "thread-name" // messageId not needed } // Dependencies ensure only one is required ``` ### Pattern 3: Progressive Complexity **Example**: Simple mode vs advanced mode ```javascript // Simple mode { "mode": "simple", "text": "{{$json.message}}" // Advanced fields hidden } // Advanced mode { "mode": "advanced", "attachments": [...], "blocks": [...], "metadata": {...} // Simple field hidden, advanced fields shown } ``` --- ## Best Practices ### ✅ Do 1. **Check dependencies when stuck** ```javascript get_property_dependencies({nodeType: "..."}); ``` 2. **Configure parent properties first** ```javascript // First: method, resource, operation // Then: dependent fields ``` 3. **Validate after changing operation** ```javascript // Operation changed → requirements changed validate_node_operation({...}); ``` 4. **Read validation errors for dependency hints** ``` Error: "body required when sendBody=true" → Hint: Set sendBody=true to enable body ``` ### ❌ Don't 1. **Don't ignore dependency errors** ```javascript // Error: "body not visible" → Check displayOptions ``` 2. **Don't hardcode all possible fields** ```javascript // Bad: Adding fields that will be hidden ``` 3. **Don't assume operations are identical** ```javascript // Each operation has unique requirements ``` --- ## Summary **Key Concepts**: - `displayOptions` control field visibility - `show` = field appears when conditions match - `hide` = field disappears when conditions match - Multiple conditions = AND logic - Multiple values = OR logic **Common Patterns**: 1. Boolean toggle (sendBody → body) 2. Resource/operation cascade (different operations → different fields) 3. Type-specific config (string vs boolean conditions) 4. Method-specific fields (GET vs POST) **Troubleshooting**: - Field required but not visible → Check dependencies - Field disappears after change → Operation changed requirements - Field doesn't save → Hidden by dependencies **Tools**: - `get_property_dependencies` - See dependency rules - `get_node_essentials` - See operation requirements - Validation errors - Hints about dependencies **Related Files**: - **[SKILL.md](SKILL.md)** - Main configuration guide - **[OPERATION_PATTERNS.md](OPERATION_PATTERNS.md)** - Common patterns by node type