rb90
rb90

Reputation: 319

Observe changes on SwiftUI TextField

I am playing around with Swift UI. I created a table view (a List) containing all my desired elements. Also the TextField change is working when pressing enter on the keyboard. Nice to build so fast a table view ;).

But now I want to track every change on the textfield. Every time user enter another text I want to send a request which triggers a search.

How could this be done in my code? I read also this documentation here https://developer.apple.com/documentation/combine/receiving_and_handling_events_with_combine

I don't now how to use it in my struct.

The proposed solution here TextField changes in SwiftUI does not work (anymore)

I would be thankful for every hint and every idea you can share with me. I am looking for hours for a solution :(.

My code looks like this:

import Foundation
import SwiftUI

struct MyListView: View {
    @ObservedObject var viewModel: MyViewModel

    @State private var query = ""

    var body: some View {

        NavigationView {
            List {
                // how to listen for changes here?
                // if I add onEditingChange here, Get the value only after the user finish search (by pressing enter on the keyboard)
                TextField(String.localizedString(forKey: "search_bar_hint"), text: self.$query) {
                    self.fetchListing()
                } 

                ForEach(viewModel.myArray, id: \.id) { arrayObject in
                    MyRow(arrayObj: arrayObject)
                }
            }
            .navigationBarTitle(navigationBarTitle())
        }
        .onAppear(perform: fetchListing)
    }

    private func fetchListing() {
        query.isEmpty ? viewModel.fetchRequest(for: nil) : viewModel.fetchRequest(for: query)
    }

    private func navigationBarTitle() -> String {
        return query.isEmpty ? String.localizedString(forKey: "my_title") : query
    }
}

Upvotes: 7

Views: 7559

Answers (2)

Zeeshan
Zeeshan

Reputation: 586

Here we go

struct ContentView: View {
    @State private var email = ""
    var body: some View {
        TextField("Email", text: $email)
            .onChange(of: email) { text in
                print(text)
            }
    }
}

Upvotes: 11

Mojtaba Hosseini
Mojtaba Hosseini

Reputation: 119128

A simple custom binding is a good start for this task:

struct ContentView: View {
    @State private var query = ""

    var body: some View {

        let binding = Binding<String>(
            get: { self.query },
            set: { self.query = $0; self.textFieldChanged($0) }
        )

        return NavigationView {
            List {
                TextField("Text", text: binding)
            }
        }
    }

    private func textFieldChanged(_ text: String) { print(text) }
}

It is tested and working

Upvotes: 17

Related Questions