Get data from view after it gets added on screen using ForEach

I have created a custom view which contains a textview, a textfield and a picker with three items.

Now this is added by iterating an array using a foreach loop. These can be more than one based on the response from the server. Now I wish to get the data back from the textfield and the textfield. I tried to use Binding in the forEach loop but it is now receiving any update done in these views.

added code details below

Below is the code that I have currently

struct CheckListCard: View {
   
  @Binding var checkListData : ChecklistModel
  @State var statusList: [String] = []
  @State var currentStatus : String = ""
  @State var currentRemark: String = ""
  @Binding var enableButtonBool: Bool
   
  var body: some View {
    VStack{
      Text("Description").padding()
        .onAppear(){
          addData()
        }
      if checkListData.description != nil{
        Text(checkListData.description!)
          .padding()
      }
      Text("Status").padding()
      if checkListData.status != nil {
        Picker("Status", selection: $currentStatus ) {
          ForEach(GeneralMethods().uniqueElementsFrom(array: statusList), id: \.self){ status in
            Text(status)
          }
        }.pickerStyle(SegmentedPickerStyle())
        .padding()
        .disabled(!enableButtonBool)
         
      }
      Text("Remarks")
      if checkListData.remarks != nil{
        TextField("Remarks", text: $currentRemark)
          .disabled(!enableButtonBool)
          .padding()
          .background(Color(.white))
          .cornerRadius(8)
          .accentColor(.gray)
           
      }else{
        TextField("Remarks", text: $currentRemark)
          .disabled(!enableButtonBool)
          .padding()
          .background(Color(.white))
          .cornerRadius(8)
           
      }
    }
struct CheckListSheet: View {
   
  @State var taskId: Int
  @State var pmTaskResponse : PmTaskResponse
  @State var checklistResponse: [ChecklistModel] = [ChecklistModel()]
  @State var enableButtonBool: Bool = false
  var body: some View {
     
    Text("Checklist Items")
      .padding()
      .font(.title)
     
    ScrollView{
       
      ForEach(checklistResponse, id:\.self){ checklist in
        CheckListCard(checkListData: Binding(get: {
          return checklist
        }, set: { (newValue) in
          checklistResponse.append(newValue)
        }) , enableButtonBool: $enableButtonBool)
      }
      if enableButtonBool{
        Button("Update"){
          updateCheckList()
        }.buttonStyle(MainButton())
      }
    }
    .onAppear(){
      getChecklists()
    }
     
  }
   

@OOPer I have attached the file for you to see. Let me know if you need anything else.

I have refactored the file and I am sending it again.

Accepted Answer

Thanks for showing the refactored code. It compiled fine. I needed to add enableButtonBool = true, but it was a great help to guess what you want to do. (I still do not understand some parts of the code, but it may be better to show what I guessed.)

I may be mistaking something, but you may want to do something like this:

import SwiftUI

struct ChecklistModel: Codable, Hashable {
    var description, remarks, status: String?
}

struct CheckListCard: View {
    @Binding var checkListData : ChecklistModel
    @State var statusList: [String] = []
    @Binding var enableButtonBool: Bool
    
    var body: some View {
        let currentStatus = Binding<String>(
            get: {checkListData.status ?? ""},
            set: {checkListData.status = $0})
        let currentRemark = Binding<String>(
            get: {checkListData.remarks ?? ""},
            set: {checkListData.remarks = $0})
        VStack{
            Text("Description").padding()
                .onAppear(){
                    addData()
                }
            if let description = checkListData.description {
                Text(description)
                    .padding()
            }
            Text("Status").padding()
            if checkListData.status != nil {
                Picker("Status", selection: currentStatus) {
                    ForEach(statusList, id: \.self){ status in
                        Text(status)
                    }
                }.pickerStyle(SegmentedPickerStyle())
                .padding()
                .disabled(!enableButtonBool)
            }
            Text("Remarks")
            if checkListData.remarks != nil {
                TextField("Remarks", text: currentRemark)
                    .disabled(!enableButtonBool)
                    .padding()
                    .background(Color(.white))
                    .cornerRadius(8)
                    .accentColor(.gray)
            } else {
                TextField("Remarks", text: currentRemark)
                    .disabled(!enableButtonBool)
                    .padding()
                    .background(Color(.white))
                    .cornerRadius(8)
            }
        }
        .padding()
        .background(Color("light_gray"))
        .foregroundColor(.black)
        .cornerRadius(8)
        .shadow(radius: 10)
        .padding()
    }
    
    func addData() {
        statusList.append("Yes")
        statusList.append("No")
        statusList.append("NA")
        if let status = checkListData.status {
            statusList.append(status) //<- Why this is needed?
        }
    }
}

struct CheckListSheet: View {
    @State var taskId: Int
    
    @State var checklistResponse: [ChecklistModel] = [ChecklistModel()]
    @State var enableButtonBool: Bool = false
    
    @State var statusList: [String] = []
    
    var body: some View {
        Text("Checklist Items")
            .padding()
            .font(.title)
        ScrollView {
            ForEach(checklistResponse.indices, id:\.self) { index in
                CheckListCard(checkListData: $checklistResponse[index],
                              enableButtonBool: $enableButtonBool)
            }
            if enableButtonBool {
                Button("Update") {
                    updateCheckList()
                }
            }
        }
        .onAppear(){
            getChecklists()
        }
    }
    
    func updateCheckList()  {
        print("this is the checklistresponse \(checklistResponse)")
    }
    
    func getChecklists()  {
        checklistResponse = [
            ChecklistModel(description: "ist item", remarks: nil, status: "Yes"),
            ChecklistModel(description: "2nd item", remarks: "Fine", status: "no")
        ]
        enableButtonBool = true
    }
}
Get data from view after it gets added on screen using ForEach
 
 
Q