Home > other >  How can I make user choose the count of TextFields in a View in SwiftUI?
How can I make user choose the count of TextFields in a View in SwiftUI?

Time:09-28

@State var multiOptions = [""]

I'm trying to create textfields for a user to populate with numbers but I want them to choose the amount of textfields they will populate. To do this I have a ForEach loop.

ForEach(multiOptions.indices, id: \.self) { index in
                TextField("Enter your option...", text: $multiOptions[index])
                    .padding()
                    .textFieldStyle(RoundedBorderTextFieldStyle())
            }

This loop creates a textfield for every empty string in multiOptions. I will include a way for the user to specify the amount of textfields they want but I was wondering if there was a way to use the users number and multiply it to multiOptions so I have the amount of empty strings that the user would like. So if the user chooses to have 6 textfields then multiOptions will have 6 empty strings.

CodePudding user response:

Here is a relatively simple answer, that is very simple to implement:

struct VariableTextFields: View {
    
    @State var fieldCount: Int = 1
    @State var multiOptions = [""]
    
    var body: some View {
        VStack {
            Button {
                multiOptions.append("")
            } label: {
                Text("Add Field")
            }
            List {
                ForEach(multiOptions.indices, id: \.self) { index in
                    TextField("Enter your option...", text: $multiOptions[index])
                        .padding()
                        .textFieldStyle(RoundedBorderTextFieldStyle())
                }
                .onDelete { offsets in
                    multiOptions.remove(atOffsets: offsets)
                }
            }
        }
    }
}

SwiftUI will keep track of the count of multiOptions in the ForEach, so all you need to do is allow the user to add and subtract from it. I implemented this behavior with a button and an .onDelete() on a List.

CodePudding user response:

Here is a possible approach for you:

struct ContentView: View {
    
    @State private var options: [String] = [String]()
    @State private var countOfOptions: Int = Int()
    
    var body: some View {
        
        VStack(spacing: 5.0) {
            
            HStack {
                
                TextField("Enter count of Options", text: Binding(get: { () -> String in return (countOfOptions != 0) ? String(describing: countOfOptions) : "" },
                                                                  set: { newValue in countOfOptions = Int(newValue) ?? 0 }), onCommit: { optionBuilder() })
                    .textFieldStyle(RoundedBorderTextFieldStyle())
                
                Button("Create Options") { optionBuilder() }
                
                Button("removeAll") { options.removeAll(); countOfOptions = 0 }.foregroundColor(.red)
                
            }
            
            ForEach(options.indices, id: \.self) { index in
                
                TextField("Enter your option...", text: Binding(get: { () -> String in return options[index] },
                                                                set: { newValue in options[index] = newValue }))
                    .textFieldStyle(RoundedBorderTextFieldStyle())
                    .transition(AnyTransition.asymmetric(insertion: AnyTransition.move(edge: Edge.trailing), removal: AnyTransition.move(edge: Edge.leading)))
                
            }
            
        }
        .padding(.horizontal)
        .animation(Animation.default, value: options)
        
    }
    
    private func optionBuilder() {
        
        if options.count < countOfOptions {
            
            for _ in 0..<countOfOptions {
                
                if (options.count < countOfOptions) { options.append(String()) }
                else { break }
                
            }
 
        }
        else {

            for _ in 0..<options.count {
                
                if (options.count > countOfOptions) { options.removeLast() }
                else { break }
                
            }
 
        }
        
    }
    
}

enter image description here

  • Related