'All textfield values are the same, SwiftUI

I have two buttons, which display data in two different layouts: grid and table. When I click on grid button, I show GridView and when I click on table button, I show - ListView.

My problem is that when user enters a textField value in grid view and click on "add to cart" button it selects all textFields and "add to cart" buttons and in ListView respectively.

It doesn't select all textFields and buttons with @State but when I switch from Grid to List, values are reset so I thought that I should declare textField values in viewModel, but it highlights all values now. Could you please give any idea how to highlight one UI element, textField or "add to cart" button, in both grid and table?

GridView ListView

 struct Products: Hashable {
    let name: String
    let price: String
    let image: String 
}

 class ProductViewModel: ObservableObject {
        @Published var gridTapped: Bool = true
        @Published var listTapped: Bool = false
        @Published var productQuantity: String = ""
        @Published var addToCart: Bool = false 
 }

struct ProductView: View {

@ObservedObject var viewModel: ProductViewModel
let columns = Array(repeating: GridItem(.flexible(), spacing: 15), count: 2)

let data = [Products(name: "IPhone 11", price: "250 0000", image: "11"),
            Products(name: "IPhone 12", price: "380 000", image: "12"),
            Products(name: "IPhone 13 pro", price: "550 000", image: "13"),
            Products(name: "IPhone 13 mini", price: "500 000", image: "13mini")
]

if viewModel.gridTapped {
    VStack {
        LazyVGrid(columns: columns, spacing: 13)  {
            ForEach(data, id:\.self) { product in
                ProductGridView(item: product, viewModel: viewModel)
            }
        }.padding(.horizontal)
         .padding(.top, 15)
         .padding(.bottom, 10)
    }
}
else if viewModel.listTapped {
    ForEach(data, id:\.self) { product in
        ListView(viewModel: viewModel, product: product)
}
}

struct ProductGridView: View {

let item: Products
@ObservedObject var viewModel: ProductViewModel

init(item: Products, viewModel: ProductViewModel) {
    self.item = item
    self.viewModel = viewModel
}

var body: some View {
    ZStack(alignment: Alignment(horizontal: .trailing, vertical: .top)) {
        VStack(alignment:.leading, spacing: 3) {
            VStack {
                Image(item.image)
                    .resizable()
                    .frame(width: 81, height: 107, alignment: .center)
                    .aspectRatio(1, contentMode: .fill)
            }
            .padding(.top, 15)
            .padding(.horizontal)
            .padding(.bottom, 10)
            
            HStack {
                VStack(alignment: .leading, spacing: 8) {
                    Text(item.name)
                        .font(.custom("Rubik-Regular", size: 15))
                        .fontWeight(.bold)
                        .fixedSize(horizontal: false, vertical: true)
                        .lineLimit(2)
                    HStack(spacing:0) {
                        Text(item.price)
                            .font(.custom("Rubik-Bold", size: 14))
                            .foregroundColor(Color.blue)
                }
                }
            }
            .frame(height: 30)
            .padding(.bottom, 30)
            .padding(.horizontal)
            
            HStack(spacing: 7) {
                TextField("1 item", text: $viewModel.productQuantity)
                    .padding()
                    .frame(width: 80, height: 45)
                    .background(Color(.lightText))

                    .cornerRadius(10)
                    .overlay(
                         RoundedRectangle(cornerRadius: 10)
                            .stroke(Color.gray, lineWidth: 1)
                        .padding(.horizontal, 10))
                
                    Button(action: {
                    viewModel.addToCart.toggle()      
                }) {
                    viewModel.addToCart ?
                    Image("cartSelected")
                        .padding(5)
                    
                    :
                    Image("cartNotSelected")
                         .padding(5)
                         
                }
            }
            .padding(.bottom, 10)
            .padding(.horizontal)
        }.frame(height: 315)
    }.cornerRadius(15)
     .shadow(color: Color.black.opacity(0.2), radius: 10, y: 5)
}
}

struct ListView: View {

let product: Products
@ObservedObject var viewModel: ProductViewModel

init(viewModel: ProductViewModel, product: Products) {
    self.viewModel = viewModel
    self.product = product
}

var body: some View {
    VStack(spacing: 20) {
                HStack(alignment: .top, spacing: 15) {
                    Image(product.image)
                        .resizable()
                        .frame(width: 73, height: 96, alignment: .center)
                        .aspectRatio(1, contentMode: .fill)
                    
                    VStack(alignment: .leading, spacing: 10) {
                        Text(product.name)
                            .fixedSize(horizontal: false, vertical: true)
                            .font(.custom("Rubik-Medium", size: 18))
                        Text(product.price)
                            .foregroundColor(.blue)
                            .font(.custom("Rubik-Medium", size: 18))
                    }
                }
                
                HStack(spacing: 20) {
                    TextField("1 item", text: $viewModel.productQuantity)
                        .padding()
                        .frame(width: 120, height: 45)
                        .background(Color(.lightText))
                        .cornerRadius(10)
                        .overlay(
                             RoundedRectangle(cornerRadius: 10)
                                .stroke(Color.gray, lineWidth: 1)
                            .padding(.horizontal, 10))
                   
                    
                    Button(action: {
                        viewModel.addToCart.toggle()   
                    }) {
                        viewModel.addToCart ?
                        HStack {
                            Image("littleTrash")
                            Text("Remove from cart")
                                .foregroundColor(Color.white)
                        }
                        .frame(width: 150)
                        .padding(.vertical, 11)
                        
                        :
                        
                        HStack {
                            Image("shopping_cart")
                            Text("Add to cart")
                                .foregroundColor(Color.white)
                        }
                        .frame(width: 150)
                        .padding(.vertical, 11)
                        
                    }
                    .background(viewModel.addToCart ? Color.red : Color.blue)
                    .cornerRadius(10)
                    .frame(width: 150, height: 45)
                }
                
            }
             .padding(.horizontal)
            .padding(.top, 15)
            .background(Color.white)
            .cornerRadius(10)
    }
}


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source