0

I have successfully displayed the data to the UI, but I want the user to be able to update my data again when tapping the "Save" button . Hope you can help me!

Profile

 I have successfully displayed the data to the UI, but I want the user to be able to update my data again when tapping the "Save" button . Hope you can help me! 
4
  • At which line are you pressing the Save button? Commented Sep 26, 2021 at 2:53
  • @ElTomato I am just successfully rendering the UI. I have not implemented Save button Commented Sep 26, 2021 at 2:58
  • show us a complete example of the code you are using, including where you want to update your data in your UI and any relevant UI context. Commented Sep 26, 2021 at 4:03
  • @workingdog I have updated my code above Commented Sep 26, 2021 at 5:00

1 Answer 1

1

There are many ways to achieve what you want. This is just one approach, by passing the profileViewModel to EditProfile:

class ProfileViewModel: ObservableObject { @Published var user = Profile(id: "", image: "", birthDay: "", role: [], gender: "", name: "") private var ref: DatabaseReference = Database.database().reference() func fetchData(userId: String? = nil) { // 8hOqqnFlfGZTj1u5tCkTdxAED2I3 ref.child("users").child(userId ?? "default").observe(.value) { [weak self] (snapshot) in guard let self = self, let value = snapshot.value else { return } do { print("user: \(value)") self.user = try FirebaseDecoder().decode(Profile.self, from: value) } catch let error { print(error) } } } func saveUser() { // save the user using your ref DatabaseReference // using setValue, or updateChildValues // see https://firebase.google.com/docs/database/ios/read-and-write } } struct EditProfile: View { @ObservedObject var profileViewModel: ProfileViewModel // <--- here var body: some View { VStack { Text(profileViewModel.user.name) // <--- you probably meant TextField .font(.custom("Poppins-Regular", size: 15)) .foregroundColor(Color.black) Text("\(profileViewModel.user.birthDay)!") .font(.custom("Poppins-Regular", size: 22)) .fontWeight(.bold) .foregroundColor(Color.black) Text("\(profileViewModel.user.gender)") .font(.custom("Poppins-Regular", size: 22)) .fontWeight(.bold) .foregroundColor(Color.black) Text(profileViewModel.user.role.first ?? "") .font(.custom("Poppins-Regular", size: 22)) .fontWeight(.bold) .foregroundColor(Color.black) Button(action: { // save the profileViewModel.user to database profileViewModel.saveUser() // <--- here }) { Text("Save") } } .padding() } } struct CategoriesView: View { @ObservedObject var viewModel = SectionViewModel() @EnvironmentObject var loginViewModel : LoginViewModel @StateObject var profileViewModel = ProfileViewModel() var body: some View { ZStack { VStack (alignment: .leading, spacing:0) { EditProfile(profileViewModel: profileViewModel) // <--- here .padding() .padding(.bottom,-10) } } .onAppear() { self.viewModel.fetchData() profileViewModel.fetchData(userId: loginViewModel.session?.uid) } } } 

EDIT1: regarding the updated code.

In your new code, in ProfileHost you are not passing ProfileViewModel. Use:

NavigationLink(destination: ProfileEditor(profileViewModel: viewModel)) { ProfileRow(profileSetting: profile) } 

And in ProfileEditor replace profile with profileViewModel.user
You will probably need to adjust profileItem and put it in a .onAppear {...} . Something like this:

struct ProfileEditor: View { @Environment(\.presentationMode) var presentationMode: Binding<PresentationMode> @ObservedObject var profileViewModel: ProfileViewModel @EnvironmentObject var loginViewModel: LoginViewModel let profileLabel: [String] = ["Name", "Account", "Gender", "Role", "Email"] @State var profileItem: [String] = [] @State var profileEditorRow: [ProfileEditorItem] = [] var body: some View { VStack { ForEach(profileEditorRow) { editor in if editor.id == 5 { ProfileEditorRow(editor: editor, showLastLine: true) } else { ProfileEditorRow(editor: editor, showLastLine: false) } } Button("Save") { profileViewModel.updateData(userId: loginViewModel.session?.uid) } } .onAppear { profileItem = [profileViewModel.user.name, profileViewModel.user.birthDay, profileViewModel.user.gender, profileViewModel.user.role.first ?? "", profileViewModel.user.birthDay] for n in 1...5 { profileEditorRow.append(ProfileEditorItem(id: n, label: profileLabel[n-1], item: profileItem[n-1])) } } } } 

EDIT2: update func

func updateData() { ref.("users").child(user.id).updateChildValues([ "name": user.name, "birthDay": user.birthDay, "gender": user.gender, "role": user.role.first ?? ""]) } 

and use this in ProfileEditor :

 Button("Save") { profileViewModel.updateData() } 
Sign up to request clarification or add additional context in comments.

19 Comments

I followed you but it doesn't work
what exactly does not work? Do you get some errors? I suspect the code you are using is not what you are showing us, for example, EditProfile does not edit anything. It's best if you can edit your question and show exactly what code you are using.
Because it divides many levels, I want to summarize you. I have updated all my current code above
I've updated my answer reflecting the new code you show.
Can you edit it in my code?
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.