How can I have a NavigationLink with a programmatically defined destination?

Viewed 155

So I am working on a list view, where tapping an item on the list opens the detail view for that item.

I also want to have a button which adds an item to the list, and immediately opens the detail view.

Something like this:


struct Item: Identifiable {
    let id: UUID
    init() {
        self.id = UUID()
    }
}

struct DetailView: View {
    let item: UUID
}

struct ContainerView: View {

    @State var items: [Item] = []

    var body: some View {
        VStack {
            List {
                ForEach(items) { item in 
                    NavigationLink(
                        "Item: \(item.id)",
                        destination: DetailView(item:item)
                    )
                }
            }

            Button("New Item") {
                let newItem = Item()
                items += [newItem]
                // now I want to go to DetailView(item:newItem)
                // how do I set the navigation link target here?
            }
        }
    }
}


How can I achieve this?

I see there is this method for programmatic navigation:

NavigationItem.init<S, V>(S, tag: V, selection: Binding<V?>, destination: () -> Destination)

But I think this will not work as the tag is not known ahead of time.

1 Answers

You almost got it, remember that a NavigationLink can only "navigate" inside NavigationView

    import Foundation
import SwiftUI

struct Item: Identifiable {
    let id: UUID
    init() {
        self.id = UUID()
    }
}

struct DetailView: View {
    let item: UUID
    
    var body: some View {
        
        Text("I'm the item \(item)")
    }
}

struct ContainerView: View {
    
    @State var items: [Item] = []
    @State var activeItem: UUID?
    
    var body: some View {
        NavigationView{
            VStack {
                List {
                    ForEach(items) { item in
                        NavigationLink(
                            destination: DetailView(item: item.id),
                            tag: item.id,
                            selection: $activeItem
                        ){
                           Text("Item: \(item.id)")
                            
                        }
                    }
                }
                
                Button("New Item") {
                    let newItem = Item()
                    items += [newItem]
                    self.activeItem = newItem.id
                    // now I want to go to DetailView(item:newItem)
                    // how do I set the navigation link target here?
                }
            }
            .navigationTitle("Main View")
        }
    }
}

enter image description here

Related