Search code examples
flutterdartflutter-provider

How to save edited todo item?


For the application, I create the functionality of editing todo item. Item has two fields: title and description. When you click on an item, it opens a modal where you can edit it. How to correctly write a function to the save button so that it saves the changes and displays them? My Provider:

class ListModel extends ChangeNotifier {
  List<EventModel> eventList = [];

  void addEventToList() {
    EventModel eventModel = EventModel(
      title: 'Event title ${eventList.length + 1}',
      detail: 'Event text ${eventList.length + 1}',
      id: '${eventList.length + 1}',
    );
    eventList.add(eventModel);

    notifyListeners();
  }

  EventModel? getEvent(String? id) {
    return eventList.firstOrNullWhere((event) => event.id == id);
  }
}

My modal window:

class EditEventBottomSheet extends StatelessWidget {
  final EventModel event;

  const EditEventBottomSheet({Key? key, required this.event}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      height: 300,
      color: Colors.amber,
      child: Center(
        child: Padding(
          padding: const EdgeInsets.all(20),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            mainAxisSize: MainAxisSize.min,
            children: [
              const Text(
                'Change Event',
                style: TextStyle(
                  fontWeight: FontWeight.bold,
                ),
              ),
              const SizedBox(height: 10),
              TextFormField(
                initialValue: event.title,
              ),
              const SizedBox(height: 10),
              TextFormField(
                initialValue: event.detail,
              ),
              const SizedBox(height: 10),
              ElevatedButton(
                child: const Text('Save Edits'),
                onPressed: () {},
              ),
              ElevatedButton(
                child: const Text('Close BottomSheet'),
                onPressed: () => Navigator.pop(context),
              )
            ],
          ),
        ),
      ),
    );
  }
}


Solution

  • You should have an EditingControllers for each textField, so, define the following before your build method

    late final titleController = TextEditingController(text: event.title);
    late final detailController = TextEditingController(text: event.detail);
    

    and inside your build method

    final provider = Provider.of<ListModel>(context);
    
    
    TextFormField(
        controller: titleController,
    ),
    const SizedBox(height: 10),
    TextFormField(
        controller: detailController,
    ),
    const SizedBox(height: 10),
    ElevatedButton(
        child: const Text('Save Edits'),
        onPressed: () {
            provider.editTodoItem(event.id, titleController.text, detailController.text);
        },
    ),
    

    And your editTodoItem should be something like:

    void editTodoItem(final String id, final String title, final String details){
        //Add a validation if you want, for example title & details must not be empty
        if(valid){
            final indexOfOld = eventList.map((e) => e.id).toList().indexOf(id);
            if (indexOfOld == -1) return;
            eventList.removeAt(indexOfOld);
            eventList.insert(indexOfOld, EventModel(
                title: title,
                detail: details,
                id: '$indexOfOld',
            ));
            notifyListeners();
        }
    }
    

    That is one of the ways of editing, (Replace the object) Also Instead of removing the object and creating a new one with the new values and insert it in old's one index, you can do the following

    if(valid){
        final event = eventList.firstWhere((e) => e.id == id);
        event.title = title;
        event.detail = details;
        notifyListeners();
    }
    

    but to be honest, the second way might not update your UI, It's been a long time since I used providers Hope this answer helps.