Another Dude
Another Dude

Reputation: 1452

SwiftUI: how to update a variable transiting from a parent view only when wanted?

I would like to pass a variable from a parent to a child view, but in this child view, use it in a text field but update this value only when a SAVE button is pressed.

I tried this:

ParentView

struct ParentView: View {
    @State private var name: String = ""
    
    var body: some View {
        HStack {
            Text("User name: \(name)")
            Spacer()
            NavigationLink(
                destination: ChildView(name: name),
                label: {
                    Text("Update name")
                }
            )
        }
    }
}

ChildView

struct ChildView: View {
    @State private var name: String = ""
    @Binding var passedName: String
    
    var body: some View {
        VStack {
            Form {
                TextField("Update name", text: $name)
                Button(action: {
                    passedName = name
                }, label: {
                    Text("SAVE")
                })
            }
        }
    }
    
    init(name: String) {
        self._passedName = .constant(name)
        self.name = name
    }        
}

Since I don't want to update the variable directly, I tried to use a name value and then only set the value of the binded passedName when the OK button is tapped. But it doesn't work.

I don't know how to do what I want to.

Thank you for your help

Upvotes: 3

Views: 3794

Answers (1)

New Dev
New Dev

Reputation: 49590

Your general approach is correct - have a state variable to represent a temporarily typed name, but a binding to represent the name "returned" to the parent.

Because the child modifies the data owned by the parent, it needs to accept a binding - not a plain String:

struct ChildView: View {
    @State private var name: String
    @Binding var passedName: String
    
    var body: some View {
        VStack {
            Form {
                TextField("Update name", text: $name)
                Button(action: {
                    passedName = name
                }, label: {
                    Text("SAVE")
                })
            }
        }
    }

    init(name: Binding<String>) {
        self._passedName = name
        self._name = State(initialValue: name.wrappedValue)
    }
}

Then, pass in a binding from the parent:

ChildView(name: $name)

Upvotes: 7

Related Questions