Reputation: 11
I have a table to display player stats on iPads (I have a makeshift grid view for iPhones). I really like the table, being sortable by different columns, and generally looking more elegant. I can also have the rows being selectable which potentially allows for two interesting features:
I am trying to do this through a context menu on each row with two buttons: a show chart button, and a destructive delete button.
The second button works totally fine. The first one trying to show the chart (or, really, at this point, any view) doesn't do it. I'm trying to show this view (again, ideally, the line chart) through a sheet to be presented when the button is pressed. But nothing is shown when the button is pressed.
Below is the code with play data. For now I just have a Text("Chart goes here") where the chart is supposed to happen. Again, nothing happens when the button in the context menu is pressed. The delete button works fine. I'm assuming it might have to do with a sheet off a button in a context menu in a row in a table?
I welcome other ideas about how to go about this too.
Thanks to all.
import SwiftUI
import Charts
struct stats: Identifiable, Equatable {
let id: UUID = UUID()
var name: String
var games: Int
var wins: Int
var carambolas: Int
var innings: Int
var longRun: Int
var avgs: [Double]
}
let ale = stats(name: "Alejandro", games: 10, wins: 8, carambolas: 30, innings: 100, longRun: 10, avgs: [0.4, 0.5, 0.3, 0.28, 0.32, 0.35, 0.27, 0.24, 0.25, 0.3])
let luis = stats(name: "Luis", games: 12, wins: 4, carambolas: 35, innings: 140, longRun: 4, avgs: [0.4, 0.5, 0.3, 0.32, 0.28, 0.32, 0.35, 0.27, 0.24, 0.25, 0.28, 0.25])
let alfredo = stats(name: "Alfredo", games: 15, wins: 7, carambolas: 40, innings: 200, longRun: 3, avgs: [0.4, 0.5, 0.3, 0.28, 0.32, 0.35, 0.27, 0.27, 0.24, 0.25, 0.28, 0.25, 0.24, 0.25, 0.2])
let diego = stats(name: "Diego", games: 18, wins: 7, carambolas: 45, innings: 250, longRun: 5, avgs: [0.4, 0.5, 0.3, 0.28, 0.32, 0.35, 0.27, 0.27, 0.24, 0.25, 0.28, 0.25, 0.24, 0.25, 0.2, 0.22, 0.23, 0.18])
struct ContentView: View {
@State var data = [ale, luis, alfredo, diego]
@State private var sortOrder = [KeyPathComparator(\stats.carambolas)]
@State private var selection: stats.ID?
@State private var showChart: Bool = true
var body: some View {
Table(of: stats.self, selection: $selection, sortOrder: $sortOrder) {
TableColumn("Player", value: \.name)
TableColumn("Games", value: \.games) {data in Text("\(data.games)")}
TableColumn("Wins", value: \.wins) {data in Text("\(data.wins)")}
TableColumn("Carambolas", value: \.carambolas) {data in Text("\(data.carambolas)")}
TableColumn("Innings", value: \.innings) {data in Text("\(data.innings)")}
TableColumn("Long Run", value: \.longRun) {data in Text("\(data.longRun)")}
TableColumn("Average", value: \.avgs.last!) {data in Text("\((data.avgs.last!), specifier: "%.3f")")}
} rows: {
ForEach(data) { row in
TableRow(row)
.contextMenu {
Button("Average Graph") {
showChart.toggle()
}
.sheet(isPresented: $showChart) {
Text("Chart goes here")
}
Divider()
Button(role: .destructive) {
if let index = data.firstIndex(of: row) {
data.remove(at: index)
}
} label: {
Label("Delete Player", systemImage: "trash")
}
}
}
}
.onChange(of: sortOrder) {
data.sort(using: sortOrder)
}
}
Upvotes: 1
Views: 73
Reputation: 36807
Sheet is a modal view and should not be inside a ForEach
loop.
So just move the .sheet(isPresented: $showChart){...}
outside the Table
,
for example, just after .onChange(of: sortOrder) {...}
and the
sheet with the Chart will appear.
Example code:
struct ContentView: View {
@State var data = [ale, luis, alfredo, diego]
@State private var sortOrder = [KeyPathComparator(\stats.carambolas)]
@State private var selection: stats.ID?
@State private var showChart: Bool = false
var body: some View {
Table(of: stats.self, selection: $selection, sortOrder: $sortOrder) {
TableColumn("Player", value: \.name)
TableColumn("Games", value: \.games) {data in Text("\(data.games)")}
TableColumn("Wins", value: \.wins) {data in Text("\(data.wins)")}
TableColumn("Carambolas", value: \.carambolas) {data in Text("\(data.carambolas)")}
TableColumn("Innings", value: \.innings) {data in Text("\(data.innings)")}
TableColumn("Long Run", value: \.longRun) {data in Text("\(data.longRun)")}
TableColumn("Average", value: \.avgs.last!) {data in Text("\((data.avgs.last!), specifier: "%.3f")")}
} rows: {
ForEach(data) { row in
TableRow(row)
.contextMenu {
Button("Average Graph") {
selection = row.id // <--- here
showChart.toggle()
}
Divider()
Button(role: .destructive) {
if let index = data.firstIndex(of: row) {
data.remove(at: index)
}
} label: {
Label("Delete Player", systemImage: "trash")
}
}
}
}
.onChange(of: sortOrder) {
data.sort(using: sortOrder)
}
.sheet(isPresented: $showChart) { // <--- here
if let selected = data.first(where: {$0.id == selection}) {
ChartView(theStat: selected)
} else {
Text("NO DATA").font(.title).bold()
}
}
}
}
struct ChartView: View {
let theStat: stats
var body: some View {
VStack {
Text(theStat.name).font(.title).bold()
Chart {
ForEach(Array(theStat.avgs.enumerated()), id: \.offset) { index, value in
LineMark(
x: .value("Index", index),
y: .value("Value", value)
)
}
}
}
}
}
Upvotes: 0