'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?
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 |
|---|
