1

I have the following InputView struct and add those InputViews dynamically within a foreach loop in another view:

struct InputView: View {

@State private var input: String = ""
var correct_input: Int

var body: some View {
    TextField("?", text: $input)
        .foregroundColor(setColor())
}

func setColor() -> Color {
    
    if (Int(input) == correct_input) {
        return Color.green
    }
    return Color.red
}
}

Up to now it is shown immediately whether the input is correct. However, I would like to add a button so that the input of all InputViews is only validated when it is clicked. How can I achieve this in SwiftUI?

2 Answers 2

2

You can be done this by making a model of text fields and use one isValid flag for each InputView for the track.

Here, is the possible demo solution.

struct TextFieldModel: Identifiable {
    var id = UUID()
    var input: String
    var correctInput: Int
    var isValidate: Bool = true
}

struct InputView: View {
    @Binding var input: TextFieldModel
    var body: some View {
        TextField("?", text: $input.input)
            .foregroundColor(input.isValidate ? Color.blue : Color.red)
    }
}

struct ContentViewTextFields: View {
    @State var arrTextFields: [TextFieldModel] = [
        .init(input: "", correctInput: 5),
        .init(input: "", correctInput: 10),
        .init(input: "", correctInput: 1)
    ]
    
    @State var isValidate: Bool = true
    
    var body: some View {
        VStack{
            ForEach(arrTextFields.indices) { index in
                InputView(input: $arrTextFields[index])
                    .background(Color.gray.opacity(0.2))
                    .padding()
            }
            Spacer()
            
            Button("Validate") {
                // Here validate all text
                arrTextFields.indices.forEach({arrTextFields[$0].isValidate = (Int(arrTextFields[$0].input) == arrTextFields[$0].correctInput) })
            }
        }
    }
}

enter image description here

Sign up to request clarification or add additional context in comments.

4 Comments

How would you achieve that with dynamically generated views? I am struggling storing these into an array after creating them.
What do you mean by dynamic? If you create dynamic it will sure have array. Please add some more details
Let's say sometimes I want to have 3 Textfields and other times 5 or 8. I have a foreach loop in the body of my View like this: ForEach(viewModel.digits, id: \.self, content: { correct_input in InputView(correct_input: correct_input) }) Is it somehow possible to append those InputViews to my array?
I suggest you to convert your digit model with this so at the end you can use this approach
1

You can have a button to check the input, setting some @State variable like correct to true if it is correct.

Example:

struct ContentView: View {
    var body: some View {
        InputView(correctInput: 5)
    }
}

struct InputView: View {
    @State private var input = ""
    @State private var correct = false
    let correctInput: Int
    
    var body: some View {
        VStack {
            TextField("?", text: $input)
                .foregroundColor(correct ? .green : .red)
            
            Button("Check answer") {
                correct = Int(input) == correctInput
            }
        }
    }
}

2 Comments

Sorry, but I would like to have a single check button for all my views. :)
@flo I'm unsure what you mean. Do you have lots of InputViews and would like to check them all at same time instead of individually?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.