I am creating a TextField dynamically inside VStack. Here TextFields are created as follows:
struct Input: View {
var title: String
@State var value:String
var disableInputMode:Bool = true
var body: some View {
VStack {
Text(title)
.frame(maxWidth: .infinity, alignment: .leading)
.foregroundColor(Color("SecondaryTextColor"))
TextField("", text: $value)
.disabled(disableInputMode)
.frame(maxWidth: .infinity, alignment: .leading)
Divider()
}
.padding()
}
}
and these TextFields depend on some other data fields (which are decided at run time):
ScrollView {
VStack {
ForEach(detailsViewModel.details) { datum in
Input(title: datum.title, value: datum.detail!)
}
}.frame(maxWidth: .infinity)
.padding()
}.background(Color("Light"))
.cornerRadius(25)
.padding()
Now, when a user enters data and tries to apply, I couldn't find how to get those inputs from other views. From the example in this case — from the above view.
CodePudding user response:
Use onChange modifier to detect TextField value changes and update it to your model.
struct Input: View {
var title: String
@State var value:String
var disableInputMode:Bool = false
var onTextChange: ((String) -> Void)?
var body: some View {
VStack {
Text(title)
.frame(maxWidth: .infinity, alignment: .leading)
.foregroundColor(Color("SecondaryTextColor"))
TextField("", text: $value)
.onChange(of: value) {
// Called each time value changes.
if onTextChange != nil {
onTextChange!($0)
}
}
.disabled(disableInputMode)
.frame(maxWidth: .infinity, alignment: .leading)
Divider()
}
.padding()
}
}
You can use it like
ScrollView {
VStack {
ForEach(detailsViewModel.details) { datum in
Input(title: datum.title, value: datum.detail) { newValue in
// Each time you will get the update
// Do what ever you want to do with the new value
// something ike
// detailsViewModel.update(value: newValue, forItem: datum.id)
print("Text value for \(datum.id) :", newValue)
}
}
}.frame(maxWidth: .infinity)
.padding()
}.background(Color("Light"))
.cornerRadius(25)
.padding()