How to Handle multiple views with form input in SwiftUI and Obtain all input values with a button click - SwiftUI?

453 Views Asked by At

I hope you're all doing well. I am new to SwiftUI and I have been working on a form UI in SwiftUI. From a UI perspective, it looks correct, but I'm facing some issues. When I fill in some values in the views and click on the button, it doesn't seem to capture the inputted values. Additionally, I'm unable to get the inputted value on preference change either. I've been trying to solve this problem for the past week.

I would greatly appreciate it if someone with knowledge of SwiftUI could review the code and let me know if I'm on the right track or if there's a better way to approach this. Here's the code I've been working on.

Here is the code i have tried:

//
//  PlatFormDataViewModel.swift

import SwiftUI

class PlatFormDataVM: ObservableObject {
   @Published var objpdata: PlatFormData
   init(_ data: PlatFormData) {
     self.objpdata = data
   }
}
struct PlatFormData: Identifiable,Hashable,Equatable
{
        var dateSeen: Date
        var id: String
        var image: String
        var kindof: String
        var subtitle: String
        var platformName: String
        var descriptions: String
        var loginId: String
        var loginPassword: String
        var others: String
        var bankName: String
        var bankBranch: String
        var bankIfsc: String
        var acName: String
        var acNumber: String
        var bankCustId: String
        var bankPassword: String
        var bankTransId: String
        var bankTransPassword: String
        var bankPin: String
        var bankMpin: String
        var bankSecurityQueAns: String
        static func == (lhs: PlatFormData, rhs: PlatFormData) -> Bool {
            lhs.id == rhs.id
        }
}
struct PlatFormDataPreferenceKey: PreferenceKey {
    static var defaultValue: [String:String] = [:]

    static func reduce(value: inout [String : String], nextValue: () -> [String : String]) {
        value = nextValue()
    }
}
//
//  AddTypeView.swift


import SwiftUI

struct AddTypeView: View {
    @Binding var isPresented: Bool
    @ObservedObject var platformdataVM = PlatFormDataVM(commonUtils().PlatFormDataPlaceholder())
    @State var pname:String = ""
    @State var description :String = ""
    @State private var previewIndex1 = 0
    var body: some View {
        
        Form {
                Section
                {
                    Text("Add Platform")
                        .bold()
                        .font(.largeTitle)
                        .clipped()
                        .foregroundColor(.black).padding(-15)
                }
                .listRowBackground(Color.clear)
                Section(header: Text("Platform Name").font(.subheadline).foregroundColor(.gray).padding(-15)) {
                    TextField("Exa. Google", text: $pname).keyboardType(.alphabet)
                    .updatedPlatFormDataValue(inputval: ["platformname":pname])
                    TypeImageSelectionPickerView()
                        .onPreferenceChange(PlatFormDataPreferenceKey.self, perform: { value in
                            if value.count > 0
                            {
                                self.platformdataVM.objpdata.image = value.first!.value
                            }
                        })
                }
                .listRowBackground(Color.white)
                .onPreferenceChange(PlatFormDataPreferenceKey.self, perform: { value in
                    if value.count > 0
                    {
                        self.platformdataVM.objpdata.platformName = value.first!.value
                    }
                })
                Section(header: Text("Description").font(.subheadline).foregroundColor(.gray).padding(-15)) {
                    TextField("Enter Description Here", text: $platformdataVM.objpdata.descriptions).keyboardType(.asciiCapable)
                        .updatedPlatFormDataValue(inputval: ["description":description])
                }
                .listRowBackground(Color.white)
                .onPreferenceChange(PlatFormDataPreferenceKey.self, perform: { value in
                    if value.count > 0
                    {
                        self.platformdataVM.objpdata.descriptions = value.first!.value
                    }
                })
                Section(header: Text("Select Option").font(.subheadline).foregroundColor(.gray).padding(-15))
                {
                    TypeSelectionPickerView()
                        .onPreferenceChange(PlatFormDataPreferenceKey.self) { value in
                        if value.count > 0
                        {
                            switch value.first?.key.lowercased().replacingOccurrences(of: " ", with: "")
                            {
                                case "kindof":
                                    self.platformdataVM.objpdata.kindof = value.first!.value
                                break
                                case "loginid":
                                    self.platformdataVM.objpdata.loginId = value.first!.value
                                break
                                case "loginpassword":
                                    self.platformdataVM.objpdata.loginPassword = value.first!.value
                                break
                                case "a/cname":
                                    self.platformdataVM.objpdata.acName = value.first!.value
                                break
                            case "name":
                                self.platformdataVM.objpdata.bankName = value.first!.value
                                break
                            case "branch":
                                self.platformdataVM.objpdata.bankBranch = value.first!.value
                                break
                            case "ifsc":
                                self.platformdataVM.objpdata.bankIfsc = value.first!.value
                                break
                            case "a/cnumber":
                                self.platformdataVM.objpdata.acNumber = value.first!.value
                                break
                            case "customerid":
                                self.platformdataVM.objpdata.bankCustId = value.first!.value
                                break
                            case "password":
                                self.platformdataVM.objpdata.bankPassword = value.first!.value
                                break
                            case "transactionpassword":
                                self.platformdataVM.objpdata.bankTransPassword = value.first!.value
                                break
                            case "transactionid":
                                self.platformdataVM.objpdata.bankTransId = value.first!.value
                                break
                            case "pin":
                                self.platformdataVM.objpdata.bankPin = value.first!.value
                                break
                            case "mpin":
                                self.platformdataVM.objpdata.bankMpin = value.first!.value
                                break
                            case "securityquestions":
                                self.platformdataVM.objpdata.bankSecurityQueAns = value.first!.value
                                break
                            case "other":
                                self.platformdataVM.objpdata.others = value.first!.value
                                break
                                default:
                                break
                            }
                            print("updated object-----\(self.platformdataVM.objpdata)")
                        }
                    }
                }
                .listRowBackground(Color.clear)
                Section {
                    FormActionView(inputvalues: self.platformdataVM.objpdata, isPresented: isPresented)
                }
                
                .listRowBackground(Color.clear)
            }.scrollContentBackground(.hidden)
            //.background(Color.green.gradient.opacity(0.3))
    }
}

#Preview {
    AddTypeView(isPresented: .constant(true))
}

struct TypeImageSelectionPickerView:View
{
    @State private var defaulticon = "house.circle.fill"
    @State private var isOpen = false
    var body:some View
    {
        HStack
        {
            Button(action: {
                withAnimation {
                    isOpen.toggle()
                }
            }, label: {
                HStack {
                    Text("Platform Icon".uppercased()).font(.subheadline).foregroundColor(.gray)
                    Spacer()
                    Image(systemName: defaulticon).font(.title3)
                }
                .updatedPlatFormDataValue(inputval: ["icon":defaulticon])
            }).tint(.gray)
        }
        SFSymbolsPicker(isPresented: $isOpen, icon: $defaulticon, category: .filterdIcons, axis: .vertical, haptic: true)
    }
}

#Preview {
    TypeImageSelectionPickerView()
}

struct TypeSelectionPickerView: View
{
    @State private var previewIndex = 0
    @State private  var selctevalue: String = ""
    var previewOptions = ["Password Only", "Multiple Inputs"]
   
    var body: some View {
        Picker("Type Of Data", selection: $previewIndex) {
            ForEach(0 ..< previewOptions.count,id: \.self) {
                Text(self.previewOptions[$0])
                   
            }
        }
        .updatedPlatFormDataValue(inputval: ["kindof":"\(previewOptions[previewIndex].lowercased().replacingOccurrences(of: " ", with: ""))"])
        .listRowSeparator(.hidden)
        .listRowBackground( Rectangle().frame(height: 45) .foregroundColor(.white).opacity(0.9) .padding(.bottom, 12).padding(.bottom, -12).cornerRadius(12))
 
        if (previewIndex == 0)
        {
            
            MultiInputView(allKeys:  ["Login ID":"" ,"Login Password":""])
        }
        else
        {
            MultiInputView(allKeys: ["Name":"" ,"Branch":"","IFSC":"","A/C Name":"","A/C Number":"","Customer ID":"","Password":"","Transaction ID":"","Transaction Password":"","PIN":"","MPIN":"","Securtiy Questions":"","Other":""])
        }
    }
}

#Preview {
    TypeSelectionPickerView()
}

struct FormActionView:View
{
    @State var inputvalues: PlatFormData
    @State  var isPresented:Bool
    var body: some View
    {
        HStack {
            Button(action: {
                print(inputvalues)
            }) {
            HStack {
                Image(systemName: .bookicon)
                Text("Save")
            }.foregroundColor(Color.white)
            .fontWeight(.bold)
            .font(.title2)
            .frame(maxWidth: .infinity)
            }.buttonStyle(.bordered)
            .background(Gradient(colors: [.indigo, .purple]))
            .cornerRadius(10.0)
            .padding(-18)
            Spacer().frame(width:50).background(Color.clear)
            Button(action: {
                        isPresented = false
            }) {
            HStack {
                Image(systemName: .closeicon).resizable().frame(width: 15,height: 15)
                Text("Close")
            }.foregroundColor(Color.white).fontWeight(.bold).font(.title3)
            }.buttonStyle(.bordered)
            .background(.indigo)
            .cornerRadius(10.0)
            .padding(-18)
        }
    }
}

#Preview {
    FormActionView(inputvalues: commonUtils().PlatFormDataPlaceholder(), isPresented: true)
}

//
//  MultiInputView.swift


import SwiftUI
extension Binding where Value == String? {
    var optionalBind: Binding<String> {
        .init(
            get: {
                wrappedValue ?? ""
            }, set: {
                wrappedValue = $0
            }
        )
    }
}
struct MultiInputView: View
{
    @State var allKeys:[String:String]
    @State private var isSecured: Bool = true
    var body: some View {
      
        let bindingToggle = Binding<Bool>(
                    get: { self.isSecured },
                    set: {
                        self.isSecured = $0;
                    }
                )
//        ZStack {
            List {
                ForEach(allKeys.sorted(by: <), id: \.key) { key, value in
                    VStack
                    {
                        
                        Text(key)
                            .frame(maxWidth: .infinity, alignment: .leading)
                            .listRowBackground(Color.clear)
                            .foregroundColor(.gray)
                        HStack
                        {
                            if key.contains("Password")
                            {
                                SecureField("Enter \(key)", text: $allKeys[key].optionalBind ).padding(10).background(Color.gray.opacity(0.3)).cornerRadius(6)
                                    .updatedPlatFormDataValue(inputval: [key:$allKeys[key].optionalBind.wrappedValue])
                                Button {
                                    bindingToggle.wrappedValue.toggle()
                                }
                            label: {
                                Image(systemName: bindingToggle.wrappedValue == true ? .eyecircleiconslash : .eyecircleicon).foregroundColor(.black)
                                    .frame(width: 27,height: 27)
                            }.buttonStyle(.bordered).background(.gray.opacity(0.3)).cornerRadius(6)
                            }
                            else
                            {
                                TextField("Enter \(key)", text: $allKeys[key].optionalBind).padding(10).background(Color.gray.opacity(0.3)).cornerRadius(6)
                                    .updatedPlatFormDataValue(inputval: [key:$allKeys[key].optionalBind.wrappedValue])
                            }
                        }
                    }
                   
                }
            .listRowSeparator(.hidden)
            .scrollContentBackground(.hidden)
        }
        .padding(10)
        .background(.white).cornerRadius(12.0).padding(EdgeInsets(top: -5, leading: -18, bottom: -12, trailing: -18))
    }
    private func textFieldChanged(_ text: String) {
        print(text)
    }
}

#Preview {
    MultiInputView(allKeys: ["Name":"" ,"Branch":"","IFSC":"","A/C Name":"","A/C Number":"","Customer ID":"","Password":"","Transaction ID":"","Transaction Password":"","PIN":"","MPIN":"","Securtiy Questions":"","Other":""])
}

Thank you so much for your time and assistance. Your help is crucial for me to overcome this challenge in SwiftUI.

Below is the screens link for the reference -

Code output link

0

There are 0 best solutions below