NavigationLink inside nested List only triggers the outer List row when clicked and doesn't navigate properly

I want to have a list of tasks and each task have a list of navigationLinks each NavigationLink has subtaskName as a label and subtaskDetails as destination and every List (tasks list and subtasks list) has .onDelete and .onMove behaviors

But when I implement the code below the navigationLink act weird. navigationLink inside List inside List is not navigating when clicked and it is only triggered and navigates to SubtaskDetailView when clicking the outer List row. How can I fix this problem?

import SwiftUI

struct ContentView: View {
    @State private var tasks: [Task] = [
        Task(name: "Task 1", subtasks: [
            Subtask(name: "Subtask 1", details: "Details for Subtask 1"),
            Subtask(name: "Subtask 2", details: "Details for Subtask 2")
        ]),
        Task(name: "Task 2", subtasks: [
            Subtask(name: "Subtask 1", details: "Details for Subtask 1"),
            Subtask(name: "Subtask 2", details: "Details for Subtask 2")
        ]),
        Task(name: "Task 3", subtasks: [
            Subtask(name: "Subtask 1", details: "Details for Subtask 1"),
            Subtask(name: "Subtask 2", details: "Details for Subtask 2")
        ])
    ]
    
    var body: some View {
        NavigationView {
            List {
                ForEach(tasks.indices, id: \.self) { index in
                    TaskView(task: $tasks[index])
                }
                .onDelete(perform: deleteTask)
                .onMove(perform: moveTask)
            }
            .navigationTitle("Tasks")
            .toolbar {
                EditButton()
            }
        }
    }
    
    private func deleteTask(at offsets: IndexSet) {
        tasks.remove(atOffsets: offsets)
    }
    
    private func moveTask(from source: IndexSet, to destination: Int) {
        tasks.move(fromOffsets: source, toOffset: destination)
    }
}

struct TaskView: View {
    @Binding var task: Task
    
    var body: some View {
        List {
            Text(task.name)
                .font(.headline)
                .padding(.bottom, 4)
            ForEach(task.subtasks.indices, id: \.self) { index in
                NavigationLink(destination: SubtaskDetailView(details: task.subtasks[index].details)) {
                    Text(task.subtasks[index].name)
                }
            }
            .onDelete(perform: { indexSet in
                task.subtasks.remove(atOffsets: indexSet)
            })
            .onMove(perform: { indices, newOffset in
                task.subtasks.move(fromOffsets: indices, toOffset: newOffset)
            })
        }
        .frame(minHeight: CGFloat(task.subtasks.count) * 80)
    }
}

struct SubtaskDetailView: View {
    let details: String
    
    var body: some View {
        Text(details)
            .navigationTitle("Subtask Details")
    }
}

struct Task: Identifiable {
    let id = UUID()
    var name: String
    var subtasks: [Subtask]
}

struct Subtask: Identifiable {
    let id = UUID()
    var name: String
    var details: String
}

Thanks!

Replies

Hi @albraa_3adil ,

If I'm understanding what you're trying to do correctly, I think you're looking for Section, not nested Lists. What I'm seeing is that you're using nested Lists so that you can add the task name as the label of the second list. Instead, you can use Section like this to get the same behavior without nesting.

struct TaskView: View {
    @Binding var task: Task
    
    var body: some View {
        Section(task.name) {
            ForEach(task.subtasks.indices, id: \.self) { index in
...

Also, if you're targeting iOS 16 and later, please use NavigationStack instead of NavigationView!