SwiftUI subviews in forms

551 views Asked by At

I want to understand if its possible to essentially have a form within a form in SwiftUI to help with code abstraction. I'll give a simple example below, so say we had the simplest form ever

Setup

struct TestForm: View {
    @State var title: String = ""
    @State var description: String = ""
    
    var body: some View {
        Form {
            Section {
                TextField("Name", text: $title)
                TextField("Description", text: $description)
            }
        }
    }
}

Essentially that will look like thissimple form

Adding a new form

Now I want to add a new subform, but I don't want its logic to convolute the main forms view. Here you can see i've added SubForm as a new view and all its dependencies (ignore the state variables, they're just there to make sure swift doesn't complain. In reality the subform can link to any state it wants to)

struct TestForm: View {
    @State var title: String = ""
    @State var description: String = ""
    @State var option: Int = 0
    
    func SubForm() -> some View {
        VStack {
            TextField("SubForm Name", text: $title)
            Picker(selection: $option, label: Text("Question Type")) {
                ForEach(Question.PayloadType.allCases, id: \.self) {
                    Text($0.rawValue)
                }
            }
        }
    }

    var body: some View {
        Form {
            Section {
                TextField("Name", text: $title)
                TextField("Description", text: $description)
            }
            
            SubForm()
        }
    }
    
    enum FormPicker: String, Codable, CaseIterable {
        case firstOption = "First Option"
        case secondOption = "Second Option"
    }
}

But now the form looks like this:

Messed up form

As you can see the Subform is essentially in one List Item. This actually causes usability issues with Navigation Links.

The obvious problem with this is that Form is essentially a List, and List's don't flatten VStacks or even other Forms (imagine that the subview was wrapped in a Form instead of the VStack it is).

However, I really would like to keep the styling that Form provides, but also want to do this logic grouping. The gold standard would look like this:

what the form should look like

Can you recommend any other way of acheiving this abstraction, while maintaining a single usable Form?

Cheers in advance

1

There are 1 answers

0
nicksarno On

Can you add the second form just as a new Section? Is this what you're looking for?

var body: some View {
        Form {
            Section {
                TextField("Name", text: $title)
                TextField("Description", text: $description)
            }
            
            Section {
                TextField("SubForm Name", text: $title)
                TextField("QuestionType", text: $description)
            }
        }
    }