A read-only tasks app is not very practical! Let’s add the ability to update the completed
state and mark/unmark our tasks as done.
First, though, we’ll extract the tasks-specific code to a separate screen named TasksScreen
:
class TasksScreen extends HookConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final state = ref.tasks.watchAll();
if (state.isLoading) {
return CircularProgressIndicator();
}
return ListView(
children: [
for (final task in state.model) Text(task.title),
],
);
}
}
Remember to return this new widget from TasksApp
:
class TasksApp extends HookConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
return MaterialApp(
home: Scaffold(
body: Center(
child: ref.watch(repositoryInitializerProvider()).when(
error: (error, _) => Text(error.toString()),
loading: () => const CircularProgressIndicator(),
data: (_) => TasksScreen(),
),
),
),
debugShowCheckedModeBanner: false,
);
}
}
Back to our TasksScreen
we are going to wrap our title text widget in a ListTile
prefixing it with a checkbox which, upon clicking, will toggle task completion:
class TasksScreen extends HookConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final state = ref.tasks.watchAll();
if (state.isLoading) {
return CircularProgressIndicator();
}
return ListView(
children: [
for (final task in state.model)
ListTile(
leading: Checkbox(
value: task.completed,
onChanged: (value) => task.toggleCompleted().save(),
),
title: Text('${task.title} [id: ${task.id}]'),
),
],
);
}
}
If only the toggleCompleted()
method existed… 🙂
Since Task
is immutable and provides no way to update fields, we return a new Task
object with the inverse boolean value of completed
, initialized via the was method.
@JsonSerializable()
@DataRepository([JSONServerAdapter])
class Task with DataModel<Task> {
@override
final int? id;
final String title;
final bool completed;
Task({this.id, required this.title, this.completed = false});
Task toggleCompleted() {
return Task(id: this.id, title: this.title, completed: !this.completed).was(this);
}
}
Hot-reload and check all boxes…
Done!
NEXT: Creating a new task