0

A newbie to SwiftUI. I have my List of items and I want to select one and have the TextField take its value, mimicking an autocomplete. How can I achieve it?

struct ContentView: View {
    
    @StateObject private var viewModel = ViewModel()
    @State private var from: String = ""
    @State private var selection: String?

    var body: some View {
        VStack {
            HStack {
                TextField("From", text: $from)
                    .textFieldStyle(.roundedBorder)
                    .onChange(of: from) { newValue in
                        viewModel.autoComplete(input: from, flightType: .from)
                    }
            }
        }
        .padding(16)
        List(viewModel.suggestions, id: \.self, selection: $selection) { suggestion in
            ZStack {
                Text(suggestion)
            }
            .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .leading)
        }
        .task {
            await viewModel.fetchData()
        }
    }
}
bruno
  • 2,154
  • 5
  • 39
  • 64
  • You could try using this operator overload solution, here [TextField with optional](https://stackoverflow.com/questions/57021722/swiftui-optional-textfield) and using `TextField("From", text: $selection ?? "")`. This way you only use one variable. – workingdog support Ukraine Aug 29 '23 at 06:45

1 Answers1

2

The easiest solution (because of the two states, from and selection not being of the same type) seems to be another .onChange modifier:

VStack {
    [...]
}
.onChange(of: self.selection) { 
     if let selection = $0 {
          self.from = selection
     }
}

Although, you could also convert your list into clickable items, instead of a selection, and completely drop the selection variable:

List(viewModel.suggestions, id: \.self) { suggestion in
    HStack {
        Text(suggestion)
        Spacer()
    }
    .contentShape(Rectangle())
    .onTapGesture {
        self.from = suggestion
    }
}
iSpain17
  • 2,502
  • 3
  • 17
  • 26