I try to show an alert view when user is going to delete a selected table-row. The delete button is part of a table-row context menu. I think this is because table-row is not a view but when moving the alert to the table view I cannot access secretItem from the ForEach loop anymore. So how to delete rows (object items) from a table with alert views on context menu buttons
Any guidance for me?
struct SecretDetailView: View {
@State private var showDeleteAlert = false
var table: some View {
Table(selection: $selection, sortOrder: $sortOrder) {
TableColumn("User Name", value: \.userName)
...
} rows: {
ForEach(secretItems) { secretItem in
TableRow(secretItem)
// Menue showing up with right click on table row for row manipulation
.contextMenu {
Button("Delete Item") {
showDeleteAlert.toggle()
}
// alert not showing up here:
.alert(isPresented: $showDeleteAlert) {
Alert(
title: Text("Do you want to delete item?"),
message: Text(""),
primaryButton: .cancel(
Text("Cancel"),
action: { }
),
secondaryButton: .destructive(
Text("Delete"),
action: {deleteSelectedSecretItem(secretItem) }
)
)
}
}
}
>Solution :
Use the alert overloads that takes in a value to be presented, such as alert(_:isPresented:presenting:actions:) or alert(item:content:) (deprecated in iOS 17). This way, you can move the alert modifier to be on the Table instead.
Add a new @State to store the item to be deleted, and set this in the context menu "Delete" button’s action.
// assuming secretItems is an array of "Item"
@State private var toBeDeletedItem: Item?
.contextMenu {
Button("Delete Item") {
showDeleteAlert.toggle()
toBeDeletedItem = item
}
}
// add this to the Table
.alert("Do you want to delete item?", isPresented: $showDeleteAlert, presenting: toBeDeletedItem) { item in
Button("Delete", role: .destructive) {
deleteSelectedSecretItem(item)
}
Button("Cancel", role: .cancel) { }
}
Or if you are on an earlier version and alert(_:isPresented:presenting:actions:) is not available:
.alert(item: $toBeDeletedItem) { item in
Alert(
title: Text("Do you want to delete item?"),
message: Text(""),
primaryButton: .cancel(
Text("Cancel"),
action: { }
),
secondaryButton: .destructive(
Text("Delete"),
action: { deleteSelectedSecretItem(item) }
)
)
}
// You don't actually need showDeleteAlert!