Reputation: 9419
I'm trying to subclass a TextField
to clean up the code. I currently have one text field "row" in my Form
, but eventually I would like to find a way to make this scalable (and have a lot more HStack
s).
Form {
Section {
HStack {
Text("Balance")
.foregroundColor(Color.white)
TextField("", text: $balance, onEditingChanged: { (changing) in
print("Changing: \(changing)")
}, onCommit: {
print("Committed!")
})
.multilineTextAlignment(.trailing)
.foregroundColor(Color.white)
.keyboardType(.numbersAndPunctuation)
.onReceive(Just(balance)) { newValue in
let filtered = newValue.filter { "0123456789".contains($0) }
if filtered != newValue {
self.balance = filtered
}
}
.placeHolder(
Text("$0.00")
.frame(maxWidth: .infinity, alignment: .trailing)
.multilineTextAlignment(.trailing)
.foregroundColor(Color(#colorLiteral(red: 0.3492315412, green: 0.3486715555, blue: 0.3704651594, alpha: 1))),
show: balance.isEmpty)
}
}
.listRowBackground(Color(#colorLiteral(red: 0.1923851669, green: 0.1917944849, blue: 0.2135801911, alpha: 1)))
}
I don't want to repeat the HStack
declaration 4 times (the number of rows). So I need to subclass. However, I need to find a way to pass the state (dollar sign) to the subclass. How? Also, is there any way to have an array of states so that I can use a ForEach
? Example:
var imaginaryArrayWithStates = [$textFieldValue1, $textFieldValue2] // you can't do this, but I would like to iterate states somehow...
// ...so that I can use a ForEach
ForEach(imaginaryArrayWithStates) { state
MyCustomTextField() // how do I pass the state to this subclass?
}
Upvotes: 1
Views: 681
Reputation: 54611
You can use @Binding
:
struct CustomTextField: View {
@Binding var value: String
var body: some View {
HStack {
Text("Balance") // can be extracted as a variable
TextField("", text: $value, onEditingChanged: { changing in
print("Changing: \(changing)")
}, onCommit: {
print("Committed!")
})
.multilineTextAlignment(.trailing)
.keyboardType(.numbersAndPunctuation)
.onReceive(Just(value)) { newValue in
let filtered = newValue.filter { "0123456789".contains($0) }
if filtered != newValue {
self.value = filtered
}
}
}
}
}
struct ContentView: View {
@State var values = ["312", "222", ""]
var body: some View {
Form {
Section {
ForEach(values.indices, id: \.self) { index in
CustomTextField(value: self.$values[index])
}
}
}
}
}
Upvotes: 2