Ignore first render in swift UI

83 views Asked by At

I am trying to show an error below a text field. if the value of text fields is less then 2 character we show an error.

The only problem is that the value must be initialised ie with empty string which triggers the error with out even the beginning of user interaction. Code is attached for reference.

class ErrorViewModel: ObservableObject{
    @Published var value: String
    var errorToShow: String {
        if(value.count < 2){
            return "invalid input"
        }else{
            return ""
        }
    }
    init(value: String) {
        self.value = value
    }
}
struct ErrorView: View {
    @ObservedObject var errorVm: ErrorViewModel
    var body: some View {
        Text(errorVm.errorToShow)
    }
}

struct TextFieldView : View {
    @State var value: String
    var body: some View {
        TextField(
            "Enter yor name",
            text: $value
        )
        ErrorView(errorVm: ErrorViewModel.init(value: value))
    }
}

#Preview {
    TextFieldView(value: "")
}

I just want to ignore the first render with the default value. So that the error is shown when user interaction begins.

2

There are 2 answers

0
Mojtaba Hosseini On

You should write the logic as you think of, so keep track of the user interaction as well, for example like:

struct TextFieldView : View {
    @State var value: String
    @State var userInteracted = false //  keep tracking
    var body: some View {
        TextField(
            "Enter yor name",
            text: Binding(get: { value ?? "" }, set: { value = $0 })
        )
        .onChange(of: value) { _, _ in userInteracted = true } //  toggle on interactions

        if userInteracted { //  make this conditional
            ErrorView(errorVm: ErrorViewModel.init(value: value))
        }
    }
}
0
Asad On

Another solution(Documentation) :

struct TextFieldView : View {
    @State var value: String = ""
    @FocusState var editing: Bool

    var body: some View {
        TextField("Enter yor name", text: $value)
            .focused($editing)

        if editing {
            ErrorView(errorVm: ErrorViewModel.init(value: value))
        }
    }
}