I have a list within a NavigationSplitView. The list has NavigationLinks, which when selected, load a detail view:
List(selection: $selectedMode) {
ForEach(modes, id: \.self) { modeInfo in
NavigationLink {
DashboardView(
parameters:
DashboardParameters(
mode: selectedMode,
moment: selectedFromMoment
)
)
} label: {
Text(modeInfo.name)
}
}
}
and then I have a picker where I want to also be able to update the DashboardView in the detail section:
Picker("", selection: $selectedFromMoment) {
ForEach(Moment.allCases.filter { moment in
moment != Moment.now
}, id: \.name) { moment in
Text(moment.name).tag(moment)
}
}.onChange(of: selectedFromMoment) { oldValue, newValue in
//I want to update detail view from here
}
Note that the view loaded (DashboardView) takes an object which has two parameters (one set from the List and one from a separate picker).
How can I get the NavigationLink to trigger also when the picker is changed? Basically, I need to load a new detail view whenever the lists changes or the picker changes.
Here is my current solution, which seems like a HUGE hack:
.onChange(of: selectedFromMoment) { oldValue, newValue in
let m = selectedMode
selectedMode = nil
Task {
try await Task.sleep(for: .seconds(0.01))
selectedMode = m
}
}
Basically, when a new value is chosen from the Picker, I clear and reset the selected item in the list, which forces the navigationlink in the list to fire again. I have to wait a tick though, as if I clear and reset in the same loop, it doesnt work.
As long as your dashboard view depends on
@State
variables, it should get redrawn whenever they change.Here's a quick example of how it works with a custom Struct that contains the selection for both the list and the picker. When you pass this struct to the detail view, it updates automatically whenever one of the values inside the struct changes.