M1X
M1X

Reputation: 5354

SwiftUI pre fill TextField from ViewModel

I have a view model called UserService. Let's says that this stores all the user data and it's automatically updated when the data is changed in Firestore.

Then I have a View with a TextField called phone. This is used as an input to get the user phone number.

This view has a ViewModel also and this vm contains the @Published var phone: String = "" property which the TextField uses.

The problem is that other than using this TextField to update the value I want it to also show the current value coming from UserService.

I do not know how to pass this data from UserService to TestViewModel. If a put UserService inside TestViewModel the property wont be updated in real time since vm inside vm is not supported yet in SwiftUI. Right now i have ended up with two separate properties. the phone inside UserService and the phone inside TestViewModel.

I thought of manually updating phone inside on init() (TestViewModel) but I'm not sure if thats the correct way to do it since I have a other properties other than phone

How can I achieve smth like this?

struct User: Identifiable, Codable {
    var phone: String
}


class UserService: ObservableObject {
    @Published var user: User?
}


struct TestView: View {
    @ObservedObject var testViewModel = TestViewModel()
    @EnvironmentObject var userService: UserService
    
    var body: some View {
        Form {
            Section(header: Text("PHONE NUMBER")) {
                TextField("Phone number", text: $testViewModel.phone)
            }
        }
    }
}


class TestViewModel: ObservableObject {
    @Published var phone: String = ""

    init() {
        prefillForm()
    }
    
    func prefillForm() {
      //
    }
    
}

Upvotes: 3

Views: 1839

Answers (1)

Asperi
Asperi

Reputation: 257533

A possible approach is to initialise vm in onAppear and sync back to userSettings in onChange, like

Section(header: Text("PHONE NUMBER")) {
    TextField("Phone number", text: $testViewModel.phone)
        .onAppear {
            testViewModel.phone = userService.user?.phone ?? ""
        }
        .onChange(of: testViewModel.phone) { value in
            userService.user?.phone = value
        }
}

Upvotes: 3

Related Questions