Skip to content

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.

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)
}
}
}
}
}

Show field when another field equals a value:

rules.add("shoe_size", rule: .equals("gender", "boy"))

Show field when another field is in an array of values:

rules.add("special_field", rule: .in("status", ["active", "pending"]))

Show field when another field is not empty:

rules.add("details", rule: .notEmpty("has_details"))

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
})

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")
])

The ConditionalField component can wrap ANY SwiftUI view:

// Conditionally show entire sections
ConditionalField(field: "show_section", form: form) {
Section("Advanced Options") {
// Multiple fields, buttons, etc.
}
}
// Conditionally show cards
ConditionalField(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 buttons
ConditionalField(field: "enable_action", form: form) {
Button("Action") {
// Handle action
}
.buttonStyle(.borderedProminent)
}
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)
}
}
}
}

Watch field values programmatically:

// Watch single field
let email = form.watch("email")
// Watch multiple fields
let fields = form.watch(["email", "name"])
// Watch all fields
let allFields = form.watchAll()
// Check if field should be visible
if form.shouldShow("shoe_size") {
// Show field
}

Fields automatically update visibility when watched fields change:

// Gender changes -> shoe_size/top_size visibility updates automatically
// No manual state management needed!
  1. Define Rules Once: Set up visibility rules in form initialization
  2. Use Descriptive Rules: Use clear field names and conditions
  3. Test Edge Cases: Ensure fields show/hide correctly for all values
  4. Combine with Validation: Use conditional fields with validation rules