Reputation: 1301
I use DB SQLite and I want to update the data, but when the data changes, nothing happens, only a warning pops up in the console (I attached it below). I tried different options, but still I can’t understand why I can’t update the data. Though create/delete works well without problems. And updating the data in the DB caused such difficulties. I would be grateful if you tell me what could be the reason.
database
Future<int> updateTodo(Todo todo) async {
Database db = await database;
return await db
.update(todoTable, todo.toMap(), where: 'id = ?', whereArgs: [todo.id]);
}
edit_todo_screen
class EditTodoScreen extends StatelessWidget {
final Todo todo;
EditTodoScreen({Key? key, required this.todo}) : super(key: key);
final _controller = TextEditingController();
@override
Widget build(BuildContext context) {
_controller.text = todo.description;
return BlocBuilder<TodoBloc, TodoState>(builder: (context, state) {
return Scaffold(
appBar: AppBar(
title: const Text('Edit Todo'),
),
body: _body(context),
);
});
}
Widget _body(context) {
return Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
children: [
TextField(
controller: _controller,
autocorrect: true,
decoration: const InputDecoration(hintText: 'Enter todo message'),
),
const SizedBox(
height: 10.0,
),
InkWell(
onTap: () {
BlocProvider.of<TodoBloc>(context).add(
UpdateTodos(
todo,
_controller.text,
),
);
Navigator.pop(context);
},
child: _updateBtn(context),
)
],
),
);
}
todo_bloc
on<UpdateTodos>((event, emit) async {
await todoRepository.updateTodo(event.todo);
final List<Todo> _loadedTodoList = await todoRepository.getAllTodos();
emit(TodoLoadedState(loadedUser: _loadedTodoList));
});
todo_event
class UpdateTodos extends TodoEvent {
final Todo todo;
const UpdateTodos(this.todo);
@override
List<Object> get props => [todo];
}
todo_list
class TodoList extends StatefulWidget {
@override
State<TodoList> createState() => _TodoListState();
}
class _TodoListState extends State<TodoList> {
@override
void initState() {
super.initState();
BlocProvider.of<TodoBloc>(context).add(LoadTodos());
}
@override
void dispose() {
BlocProvider.of<TodoBloc>(context).close();
super.dispose();
}
@override
Widget build(BuildContext context) {
final TodoBloc todoBloc = context.read<TodoBloc>();
return BlocBuilder<TodoBloc, TodoState>(builder: (context, state) {
if (state is TodoEmptyState) {
return const Center(
child: Text(
'No Todo',
style: TextStyle(fontSize: 20.0),
),
);
}
if (state is TodoLoadingState) {
return const Center(child: CircularProgressIndicator());
}
if (state is TodoLoadedState) {
return ListView.builder(
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: state.loadedUser.length,
itemBuilder: (context, index) => ListTile(
title: Column(children: [
Text('${state.loadedUser[index].description}'),
Text('${state.loadedUser[index].id}'),
]),
trailing: IconButton(
onPressed: () {
todoBloc.add(DeleteTodos(id: state.loadedUser[index].id));
// todoBloc.add(LoadTodos());
},
icon: const Icon(Icons.delete),
),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => EditTodoScreen(
todo: Todo(
description:
'${state.loadedUser[index].description}'),
)),
);
todo_model
class Todo {
int? id;
late String description;
// bool isDone = false;
Todo({this.id, required this.description});
Map<String, dynamic> toMap() {
final map = <String, dynamic>{};
map['id'] = id;
map['description'] = description;
// map['isDone'] = isDone == false ? 0 : 1;
return map;
}
Todo.fromMap(Map<String, dynamic> map) {
id = map['id'];
description = map['description'];
// isDone = map['isDone'] == 0 ? false : true;
}
}
todo_repository
class TodoRepository {
final db = DBProvider();
Future getAllTodos() => db.getTodos();
Future insertTodo(Todo todo) => db.createTodo(todo);
Future updateTodo(Todo todo) => db.updateTodo(todo);
Future deleteTodo(int id) => db.deleteTodo(id);
Future deleteAllTodo(int id) => db.deleteAllTodo(id);
}
When I click on the button, this is the warning in the console
Upvotes: 0
Views: 185
Reputation: 935
return await db
.update(todoTable, todo.toMap(), where: 'id = ?', whereArgs: [todo.id]);
The error you're getting happens here because todo id is null. This is what you're doing when routing to EditTodoScreen
:
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => EditTodoScreen(
todo: Todo(
description: '${state.loadedUser[index].description}',
),
),
),
);
Notice the todo here:
todo: Todo(
description: '${state.loadedUser[index].description}',
),
You're only passing description, but no id. This is why you get that error when trying to update.
You already have access to the todo you're trying to update so you can just pass that instead of creating a new one. Use this code for routing to EditTodoScreen
:
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => EditTodoScreen(
todo: state.loadedUser[index],
),
),
);
Upvotes: 1