[SOLVED] Adding and removing buttons in ForEach view

Issue

Here is my code:

                        ForEach(StaffList, id: \.self) { item in
                                HStack {
                                    Text("\(item)")
                                    Spacer(minLength: 0)
                                    Image(systemName: "x.circle")
                                        .foregroundColor(.red)
                                        .onTapGesture {
                                            //TODO: Remove user UUID from array + Show add button
                                        }
                                    Image(systemName: "checkmark.circle")
                                        .foregroundColor(.blue)
                                        .onTapGesture {
                                            //TODO: Add user UUID from array + Show remove button
                                        }
                            }
                        }

A simple solution would be one @state variable in the Struct for every one in the loop, but it arises a problem. Because each button is assigned to the same variable. When the variable changes, all of them change. For example:


@State var isShowing = false


                        ForEach(StaffList, id: \.self) { item in
                                HStack {
                                    Text("\(item)")
                                    Spacer(minLength: 0)
                                if isShowing {
                                    Image(systemName: "x.circle")
                                        .foregroundColor(.red)
                                        .onTapGesture {
                                            //TODO: Remove user UUID from array + Show add button
                                            is Showing = true
                                        }
                                    } else {
                                    Image(systemName: "checkmark.circle")
                                        .foregroundColor(.blue)
                                        .onTapGesture {
                                            //TODO: Add user UUID from array + Show remove button
                                            isShowing = false
                                        }
                                 }
                            }
                        }

Technically this works, but take into consideration the unlimited amount of people in StaffList. If I click X on one of them, they would all update to show a Checkmark. The goal is ForEach, they all have their own set of changes if that makes since. So when I click X on one of them, it updates and shows the Checkmark but none of the others in the ForEach loop update, and still show the X.

Solution

Edit
After the latest update in the question, here’s the corrected answer to address the issue "Buttons are changing for all items rather than for each single item"

You can hide or show the buttons using an @State variable. There are several tutorials online.

But to change the buttons for each single member of StaffList separately (which we’d better call staffList since it’s a variable), you need to have one @State variable for each item in the ForEach. This can be achieved by creating a secondary view, which in the example below I called ItemView.

Here’s the code:

struct YourMainView: View {
    // This is not the right place for the @State variable that affects each single item
    // @State var isShowing = false

    // Other variable declarations

    var body: some View {

        ForEach(staffList, id: \.self) { item in
            ItemView(item: item)
        }
    }
}

// This is the view of each single item
struct ItemView: View {

    let item: StaffListItemType    // Whatever the actual type is

    // Here is the right place to manage it (always make it private)
    @State private var isShowing = false

    var body: some View {
            HStack {
               Text("\(item)")
               Spacer(minLength: 0)
               if isShowing {
                    Image(systemName: "x.circle")
                        .foregroundColor(.red)
                        .onTapGesture {
                            //TODO: Remove user UUID from array + Show add button
                            isShowing = false  // If it's true, it needs to become false. Or, use .toggle()
                         }
               } else {
                    Image(systemName: "checkmark.circle")
                        .foregroundColor(.blue)
                        .onTapGesture {
                             //TODO: Add user UUID from array + Show remove button
                             isShowing = true  // If it's false, it needs to become true. Or, use .toggle()
                         }
               }
            }
    }
}

Answered By – HunterLion

Answer Checked By – Jay B. (BugsFixing Admin)

Leave a Reply

Your email address will not be published.