Reputation: 597
I'm trying to shape out the best way to pass the info back from child to parent when both use View Models and need the item to perform some work. There are a lot of similar topics on SO, but none seems to tackle the issue that I've got. I understand there might be multiple solutions to solve this project, but none of them convince me to be correct.
Parent
screen when you have a selected item and can save it later
struct ParentView: View {
@StateObject viewModel = ParentViewModel()
}
class ParentViewModel: : ObservableObject {
@Published var selectedItem: Item?
func saveSelectedItem() {
// some logic to perform the request and save selectedItem, of course when it is not nil
}
}
ChildView
Fetches all the possible items and allows selecting the item which should be later passed to parent.
struct ChildView: View {
@StateObject viewModel = ChildViewModel()
**(Problem)**
// presents the list of all the items and highlights the current one (if not nil)
// on click sends the info back to Parent
}
class ChildViewModel: : ObservableObject {
@Published var items: [Item] = []
**(Problem)**
func loadItems() {
// fetches the items and sorts them
}
}
What I would like to do is to pass selectedItem
to the ChildView
and be notified when it is selected there on the list, but the child view model needs this to properly sort the items.
PROBLEM
selectedItem
to the child and use it in ViewModel
?If I pass it as a Binding
then the ChildView
owns it, and I require this in my ChildViewModel
to sort the items based on selectedItem
.
If I perform an action to highlight the selected item based on state of the ChildViewModel
(items) and selectedItem
isn't a bit of a mess?
struct ChildView: View {
@StateObject viewModel = ChildViewModel()
@Binding var selectedItem: Item? // How can I use this in ChildViewModel, I need it to sort fetched items properly
}
ViewModel
as it is part of the SwiftUI framework?
class ChildViewModel: : ObservableObject {
@Published var items: [Item] = []
@Binding var selectedItem: Item? // I guess this is not correct, I don't even know how to pass it here
}
ChildViewModel
with wrappedValue
of the selectedItem
but I would love to use SwiftUI/Combine approach.Upvotes: 2
Views: 4479
Reputation: 41
In SwiftUI, you can use a combination of @Binding and @State to pass data back to a parent view.
Here's an example:
struct ParentView: View {
@State private var selectedItem: Item?
var body: some View {
VStack {
// Other views...
ChildView(selectedItem: $selectedItem)
}
}
}
struct ChildView: View {
@Binding var selectedItem: Item?
var body: some View {
List {
// List of items...
Button(action: {
self.selectedItem = item
}) {
Text(item.name)
}
}
}
}
In this example, the ChildView has a selectedItem binding that is passed in from the parent view. When a user taps on one of the items in the list, the selectedItem is updated with the selected item. This change is automatically propagated back to the parent view because of the @Binding property wrapper.
Upvotes: 4