Conditional Fields
ZyraForm supports conditional field rendering, similar to React Hook Form’s watch API. Fields can be shown or hidden based on the values of other fields.
Basic Conditional Fields
Section titled “Basic Conditional Fields”struct ActivityFormView: View { @StateObject var form = PowerSyncForm<ActivityFormValues>( schema: ActivitySchema, visibilityRules: { var rules = FieldVisibilityRules() // Show shoe_size only if gender is "boy" rules.add("shoe_size", rule: .equals("gender", "boy")) // Show top_size only if gender is "girl" rules.add("top_size", rule: .equals("gender", "girl")) return rules }() )
var body: some View { Form { // Gender field (always visible) if let genderBinding = form.binding(for: "gender") { Picker("Gender", selection: genderBinding) { Text("Boy").tag("boy") Text("Girl").tag("girl") } .pickerStyle(.segmented) }
// Conditionally show shoe_size for boys ConditionalFormField(field: "shoe_size", form: form, label: "Shoe Size") { if let binding = form.intBinding(for: "shoe_size") { TextField("Shoe Size", text: binding) .keyboardType(.numberPad) } }
// Conditionally show top_size for girls ConditionalFormField(field: "top_size", form: form, label: "Top Size") { if let binding = form.binding(for: "top_size") { TextField("Top Size", text: binding) } } } }}Conditional Field Rules
Section titled “Conditional Field Rules”Equals Rule
Section titled “Equals Rule”Show field when another field equals a value:
rules.add("shoe_size", rule: .equals("gender", "boy"))In Array Rule
Section titled “In Array Rule”Show field when another field is in an array of values:
rules.add("special_field", rule: .in("status", ["active", "pending"]))Not Empty Rule
Section titled “Not Empty Rule”Show field when another field is not empty:
rules.add("details", rule: .notEmpty("has_details"))Custom Rule
Section titled “Custom Rule”Create custom conditions:
rules.add("advanced_options", rule: .custom("user_type") { value in if let userType = value as? String { return userType == "admin" || userType == "moderator" } return false})Multiple Conditions
Section titled “Multiple Conditions”Fields can have multiple conditions (ALL must be true):
var rules = FieldVisibilityRules()rules.add("payment_details", rules: [ .equals("payment_method", "credit_card"), .notEmpty("user_account")])ConditionalField Component
Section titled “ConditionalField Component”The ConditionalField component can wrap ANY SwiftUI view:
// Conditionally show entire sectionsConditionalField(field: "show_section", form: form) { Section("Advanced Options") { // Multiple fields, buttons, etc. }}
// Conditionally show cardsConditionalField(field: "show_card", form: form) { VStack(spacing: 12) { Image(systemName: "star.fill") Text("Featured Content") } .padding() .background(Color.blue.opacity(0.1)) .cornerRadius(12)}
// Conditionally show buttonsConditionalField(field: "enable_action", form: form) { Button("Action") { // Handle action } .buttonStyle(.borderedProminent)}Complete Example
Section titled “Complete Example”struct FlexibleConditionalExample: View { @StateObject var form = PowerSyncForm<ActivityFormValues>( schema: ActivitySchema, visibilityRules: { var rules = FieldVisibilityRules() rules.add("bowling_section", rule: .equals("gender", "boy")) rules.add("swimming_section", rule: .equals("gender", "girl")) return rules }() )
var body: some View { Form { Section("Gender") { if let genderBinding = form.binding(for: "gender") { Picker("Gender", selection: genderBinding) { Text("Boy").tag("boy") Text("Girl").tag("girl") } } }
// Conditionally show ENTIRE sections ConditionalField(field: "bowling_section", form: form) { Section("Bowling Information") { Text("Boys will be going bowling!") .font(.headline) .foregroundColor(.blue)
Image(systemName: "figure.bowling") .font(.largeTitle)
if let binding = form.intBinding(for: "shoe_size") { TextField("Shoe Size", text: binding) } } }
// Conditionally show cards ConditionalField(field: "swimming_section", form: form) { VStack(alignment: .leading, spacing: 16) { HStack { Image(systemName: "tshirt.fill") .font(.title2) Text("Swimming Attire") .font(.headline) } .foregroundColor(.teal)
if let binding = form.binding(for: "top_size") { TextField("Top Size", text: binding) } } .padding() .background(Color.teal.opacity(0.1)) .cornerRadius(12) } } }}Field Watching
Section titled “Field Watching”Watch field values programmatically:
// Watch single fieldlet email = form.watch("email")
// Watch multiple fieldslet fields = form.watch(["email", "name"])
// Watch all fieldslet allFields = form.watchAll()
// Check if field should be visibleif form.shouldShow("shoe_size") { // Show field}Dynamic Visibility
Section titled “Dynamic Visibility”Fields automatically update visibility when watched fields change:
// Gender changes -> shoe_size/top_size visibility updates automatically// No manual state management needed!Best Practices
Section titled “Best Practices”- Define Rules Once: Set up visibility rules in form initialization
- Use Descriptive Rules: Use clear field names and conditions
- Test Edge Cases: Ensure fields show/hide correctly for all values
- Combine with Validation: Use conditional fields with validation rules
Next Steps
Section titled “Next Steps”- Form Components - Learn about form bindings
- Validation - Add validation to conditional fields