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),
)
],
),
),
),
);
}
}
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.