When you add on child line, what do you add ? A child of the parent ? A child of the child ?
I need to have both for each line item.
So simple! Remove some tests.
Here is an updated code…
struct ContentView: View {
@State var data: [FileItem] = [
FileItem(name: "First", children: [FileItem(name: "childF1"), FileItem(name: "childF2")]),
FileItem(name: "Second", children: [FileItem(name: "childS1"), FileItem(name: "childS2"), FileItem(name: "childS3")]),
FileItem(name: "Third", children: [FileItem(name: "childT1"), FileItem(name: "childT2")]),
]
@FocusState private var focusedField: String?
var body: some View {
List($data, children: \.children) { $item in
HStack {
TextField("", text: $item.name)
.focused($focusedField, equals: item.name) // avoid keyboard to disappear at each character
.task {
self.focusedField = item.name
}
// Text(item.name)
// If there are no children, we cannot remove it
if item.children != nil { // So it is parent, maybe with no child []
Spacer()
Button("Add child") {
// let's search its position in data
print("added")
for (index, parent) in data.enumerated() {
if parent.name == item.name && parent.children != nil { // double check on nil
data[index].children!.append(FileItem(name: "new child"))
}
}
}
.buttonStyle(.borderless)
}
// if item.children == nil || item.children!.isEmpty { // nil when item is child, empty for parent
Spacer()
Button("Remove") {
// This is a simple implementation if only children, no grandChildren
// if grandchildren, need to have a recursive search for the parent
var deleteDone = false
for (index, individual) in data.enumerated() {
// remove child
if !deleteDone {
if individual.children != nil && !individual.children!.isEmpty {
for child in individual.children! {
if child.name == item.name {
var newChildren = individual.children!
newChildren.removeAll(where: { $0.name == item.name })
data[index].children = newChildren
deleteDone = true
break
}
}
}
} // REMOVE THIS -> else {
// remove parent
if !deleteDone {
for (index, individual) in data.enumerated() {
if individual.name == item.name {
data.remove(at: index)
deleteDone = true
break
}
}
}
// }
}
}
.buttonStyle(.borderless)
// }
}
}
}
}
There are still some tuning to be done (error when removing an added child). But that should give you a start point.
As I explained, if you want more levels, you can use the same struct and List. But you will have to write the function to search for an item in the hierarchy in order to add or remove it in the data. That's a good exercise.