Revo Docs
SwiftUI Integration

RevoValidation provides seamless integration with SwiftUI through the FormValidator class and view modifiers that enable real-time validation in your forms.

FormValidator

The FormValidator is an ObservableObject that manages validation state across multiple form fields. It tracks validation errors and provides an isValid property to determine if the entire form is valid.

@StateObject private var formValidator = FormValidator()

// Check if form is valid
if formValidator.isValid {
    // Proceed with form submission
}

// Get combined error messages
let errors = formValidator.errorMessage
Copied!

Using ValidatedTextField

The ValidatedTextField component provides a pre-built text field with built-in validation support.

@State private var name: String = ""

ValidatedTextField(
    "Name",
    text: $name,
    formValidator: formValidator,
    rules: "required|length:3"
)
Copied!

Using the .rules() Modifier

Apply validation rules to any TextField using the .rules() view modifier. This provides more flexibility while maintaining validation functionality.

@State private var email: String = ""

TextField("Email", text: $email)
    .rules(
        formValidator: formValidator,
        $email,
        "required|email",
        fieldId: "email"
    )
Copied!

Complete Example

A complete form example showing multiple fields with different validation rules.

import SwiftUI
import RevoValidation

struct ValidationForm: View {
    @StateObject private var formValidator = FormValidator()
    @State private var name: String = ""
    @State private var email: String = ""
    @State private var password: String = ""
    @State private var url: String = ""
    
    var body: some View {
        Form {
            ValidatedTextField(
                "Name",
                text: $name,
                formValidator: formValidator,
                rules: "required|length:3"
            )
            
            TextField("Email", text: $email)
                .rules(
                    formValidator: formValidator,
                    $email,
                    "required|email",
                    fieldId: "email"
                )
            
            SecureField("Password", text: $password)
                .rules(
                    formValidator: formValidator,
                    $password,
                    "required|length:8|containsNumber",
                    fieldId: "password"
                )
            
            TextField("URL", text: $url)
                .rules(
                    formValidator: formValidator,
                    $url,
                    "url",
                    fieldId: "url"
                )
            
            Button("Submit") {
                if formValidator.validate() {
                    // Form is valid, proceed with submission
                    submitForm()
                }
            }
            .disabled(!formValidator.isValid)
            
            if !formValidator.errorMessage.isEmpty {
                Text(formValidator.errorMessage)
                    .font(.caption)
                    .foregroundStyle(.secondary)
            }
        }
    }
    
    func submitForm() {
        // Handle form submission
    }
}
Copied!

Validation Features

  • Real-time validation: Fields are validated as the user types
  • Visual feedback: Invalid fields show an error icon and error message
  • Form-level validation: The isValid property reflects the state of all fields
  • Error messages: Access individual field errors or combined error messages
  • Disabled state: Easily disable submit buttons when the form is invalid

Dynamic Rules

You can provide dynamic rules using a closure that returns rules based on the current state.

@State private var accountType: String = "personal"
@State private var businessName: String = ""

TextField("Business Name", text: $businessName)
    .rules(
        formValidator: formValidator,
        $businessName,
        "",
        fieldId: "businessName",
        rulesProvider: {
            // Only require business name if account type is business
            if accountType == "business" {
                return Rules(stringLiteral: "required|length:3")
            }
            return Rules()
        }
    )
Copied!