'Binding ViewModel and TextFields with SwiftUI
I'm looking for the best way to create a bind between textfields
and ViewModel
.
At the moment I'm creating a @State
for each textfield and I'm manually sending the value from textfield to the viewModel properties when needed. I'm pretty sure this is not the best way to go... Is there a way to bind the TextField
with the ViewModel
property?
This is my current code:
struct SigninView: View {
@State var username:String = ""
@State var password:String = ""
var viewModel:SignInViewModel
var body: some View {
VStack(alignment: .leading, spacing: 15.0){
DefaultTextField(placeholder: "username", value: $username)
DefaultTextField(placeholder: "password", value: $password)
Spacer()
FillButton(title:"Sign In"){
///// IS THIS CORRECT?
self.viewModel.email = self.username
self.viewModel.password = self.password
//------------------
self.viewModel.signin()
}
}.padding()
}
}
The view model is something like:
class SignInViewModel:ObservableObject{
var username:String? = nil
var password:String? = nil
Solution 1:[1]
I think we can simplify it with below code.
class SignInViewModel: ObservableObject{
@Published var username = ""
@Published var password = ""
}
struct SigninView: View {
@ObservedObject var viewModel = SignInViewModel()
var body: some View {
VStack(alignment: .leading, spacing: 15.0){
TextField("username", text: $viewModel.username)
TextField("password", text: $viewModel.password)
Spacer()
Button("Sign In"){
print("User: \(self.viewModel.username)")
print("Pass: \(self.viewModel.password)")
}
}.padding()
}
}
Solution 2:[2]
Here is possible approach (of course I don't have your custom views, so just replaced with standard, but the idea is the same). Tested with Xcode 11.2/iOS 13.2
class SignInViewModel: ObservableObject{
@Published var username:String? = nil
@Published var password:String? = nil
}
struct SigninView: View {
@ObservedObject var viewModel = SignInViewModel()
var body: some View {
VStack(alignment: .leading, spacing: 15.0){
TextField("username", text: Binding<String>(
get: {self.viewModel.username ?? ""},
set: {self.viewModel.username = $0}))
TextField("password", text: Binding<String>(
get: {self.viewModel.password ?? ""},
set: {self.viewModel.password = $0}))
Spacer()
Button("Sign In"){
print("User: \(self.viewModel.username)")
print("Pass: \(self.viewModel.password)")
}
}.padding()
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Satyam |
Solution 2 |