I can't find how to get user input and update my name on the TodoListView All code below . Nothing much but i can't make it. (in my model i have id=UUID and name=String)
ChangeTodoView(On this view i try to get users input and change the value)
struct ChangeTodoView: View {
@State var not: String
@ObservedObject var todoVM = TodoListViewModel()
init(not: String){
self.not = not
}
var body: some View {
VStack{
Text("Enter Your Note")
.foregroundColor(Color.gray)
Spacer(minLength: 30)
Form {
TextEditor(text: $not)
Button(action: {
// todoVM.items[1] = not
//
todoVM.rename(indexSet: , not: not)
}, label: {
Text("Save")
}).disabled(not.isEmpty)
}
}
}
TodoListView(on this page i open ChangeTodoView)
struct ToDoListView: View {
@ObservedObject var todoVM = TodoListViewModel()
var body: some View {
NavigationView{
List{
ForEach(todoVM.items){item in
NavigationLink(
destination: ChangeTodoView(not: ""),
label : {
Text(item.name)
})
}
}
.navigationTitle("Todo App")
.navigationBarTitleDisplayMode(.large)
.toolbar {
ToolbarItemGroup(placement: .navigationBarTrailing){
EditButton()
Button {
todoVM.addItem()
} label: {
Image(systemName: "plus")
}
}
}
}
}
}
TodoListViewModel(rename function is my updating function. i try to get index and change that name to new name )
class TodoListViewModel: ObservableObject{
@Published var items = [Item(id: UUID(), name: "note1"), Item(id: UUID(), name: "note2"), Item(id: UUID(), name: "note3")]
init(){
}
func rename(indexSet: IndexSet, not: String) -> String{
for index in indexSet{
items[index].name = not
}
return not
}
}
CodePudding user response:
The most important change that has to happen is that you have to pass a single instance of the TodoListViewModel between your views. Right now, because you're creating a second instance of it in ChangeTodoView, your changes never get back to the original parent view (which, again, has a different instance of the view model).
I had to make a couple of other changes to your code because there was information left out about your indexSet and how you were deriving that, but that's all secondary to the issue of the single instance of the view model (so, make sure your only use TodoListViewModel() once).
struct Item : Identifiable {
var id: UUID
var name: String
}
class TodoListViewModel: ObservableObject{
@Published var items = [Item(id: UUID(), name: "note1"), Item(id: UUID(), name: "note2"), Item(id: UUID(), name: "note3")]
func rename(id: UUID, not: String) {
items = items.map { item -> Item in
if item.id == id {
var copy = item
copy.name = not
return copy
} else {
return item
}
}
}
}
struct ToDoListView: View {
@ObservedObject var todoVM = TodoListViewModel()
var body: some View {
NavigationView{
List{
ForEach(todoVM.items){ item in
NavigationLink(
destination: ChangeTodoView(id: item.id, not: "", todoVM: todoVM), //<-- pass the instance
label : {
Text(item.name)
})
}
}
}
}
}
struct ChangeTodoView: View {
var id: UUID
@State var not : String
@ObservedObject var todoVM : TodoListViewModel //<-- Passed from parent view
var body: some View {
VStack{
Text("Enter Your Note")
.foregroundColor(Color.gray)
Spacer(minLength: 30)
Form {
TextEditor(text: $not)
Button(action: {
todoVM.rename(id: id, not: not)
}, label: {
Text("Save")
}).disabled(not.isEmpty)
}
}
}
}
