SwiftUI passing a saved value to parent view

Viewed 1558

I am fairly new to SwiftUI I am trying to figure out the best way to pass data from a child view to parent?

Thanks for the help I come from a Javascript (React) background so this is a little different for me

The way my child view works is the user clicks on an image to select that image.

I have @State binding that saves the imgUrl which is a String referring to name in Assets.

I am just not sure about the best way to pass that value to the parent component.

Here is the child view (imageSelector)

struct ImageSelector: View {
    @State private var windowImgs = ["1", "2", "3","4","5","6","7","8","9","10","11","12","13", "14","15","16","17","18"]
    
    @State private var imgPicked = ""
    
    var body: some View{
        ScrollView(Axis.Set.horizontal, showsIndicators: true){
            HStack{
                ForEach(0..<18){num in
                    Button(action:{
                        self.imgPicked = self.windowImgs[num]
                        print(self.imgPicked)
                    }){
                        Image("\(self.windowImgs[num])")
                            .renderingMode(.original)
                            .resizable()
                            .cornerRadius(4)
                            .frame(width: 100, height: 100)
                    }
                }
            }
        }
    }
}

Here is the parent view (AddCounterForm)

struct AddCounterForm: View {
    @Environment(\.presentationMode) var presentationMode
    @State private var pickedImg: String = "defaultImg"
    @State private var price: String = "0.0"
    @State private var qty: String = "0"
    var body: some View {
        VStack (spacing: 40){
            HStack {
                Button("Cancel"){
                    self.presentationMode.wrappedValue.dismiss()
                }
                .foregroundColor(.red)
                Spacer()
                Button("Save"){
                    
                }
            }
            HStack {
                VStack (spacing: 20){
                    TextField("Window type", text: /*@START_MENU_TOKEN@*//*@PLACEHOLDER=Value@*/.constant("")/*@END_MENU_TOKEN@*/)
                    TextField("Window location", text: /*@START_MENU_TOKEN@*//*@PLACEHOLDER=Value@*/.constant("")/*@END_MENU_TOKEN@*/)
                }
                .textFieldStyle(RoundedBorderTextFieldStyle())
                Image(pickedImg)
                    .resizable()
                    .cornerRadius(4)
                    .frame(width: 90, height: 90)
                    .padding(.leading)
            }
            
            HStack {
                Text("Price")
                TextField("", text:$price)
                    .frame(width: 70)
                    .textFieldStyle(RoundedBorderTextFieldStyle())
                    .keyboardType(.numberPad)
                Spacer()
                Text("Qty")
                TextField("", text:$qty)
                    .frame(width: 70)
                    .textFieldStyle(RoundedBorderTextFieldStyle())
                    .keyboardType(.numberPad)
            }
            VStack {
                Text("Select an image")
                    .foregroundColor(.blue)
                ImageSelector()
                    .padding(.bottom)
                
                Button("Use your own image"){
                    //method
                }
                .frame(width: 180, height: 40)
                .background(Color.blue)
                .clipShape(Capsule())
                .foregroundColor(.white)
                .padding(.top)
            }
            
        }
        .padding()
    }
}

Solution for preview thanks for the help from @Asperi & @neverwinterMoon

struct ImageSelector_Previews: PreviewProvider {
    static var previews: some View {
        PreviewWrapper()
    }
}

struct PreviewWrapper: View {
    @State(initialValue: "") var imgPicked: String
    
    var body: some View {
        ImageSelector(imgPicked: $imgPicked)
    }
}
1 Answers

In this case Binding is most appropriate

struct ImageSelector: View {
   @Binding var imgPicked: String

and use

ImageSelector(imgPicked: $pickedImg)
    .padding(.bottom)
Related