'How can I update a filtered list in Flutter?
I am developing a todo app in Flutter.
I'm currently trying to delete all completed todos, but somehow I couldn't update the completed part in my main list. I am using Provider as state management.
- What I want to do: When I click the Clear Todos button, delete all the completed todos in my todos list. I don't want to delete all the todos. I just want to clear all "completed" todos.
TodosProvider codes
import 'dart:collection';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:todo_app/Models/todo.dart';
class TodosProvider extends ChangeNotifier {
SharedPreferences? sharedPreferences;
//initial state
List<Todo> todos = [];
// getter
UnmodifiableListView<Todo> get allTodos =>
UnmodifiableListView(todos.reversed);
UnmodifiableListView<Todo> get completedTodos =>
UnmodifiableListView(todos.reversed.where((todo) => todo.complete));
UnmodifiableListView<Todo> get unCompletedTodos =>
UnmodifiableListView(todos.reversed.where((todo) => !todo.complete));
// methods for Todo
void addTodo(Todo todo) {
todos.add(todo);
saveDataToLocalStorage();
notifyListeners();
}
void removeTodo(Todo todo) {
todos.remove(todo);
updateDataToLocalStorage();
checkCompletedTodos();
notifyListeners();
}
bool checkCompletedTodos() {
if (completedTodos.isEmpty) {
notifyListeners();
return true;
}
notifyListeners();
return false;
}
void removeCompletedTodos() {
List<Todo> compTodos = (todos.where((todo) => todo.complete).toList());
print('length before delete : ${compTodos.length}');
compTodos.clear();
todos.where((todo) => todo.complete) == compTodos;
print('length after clear: ${compTodos.length}');
todos.addAll(compTodos);
updateDataToLocalStorage();
print('List deleted');
notifyListeners();
}
void toggleTodo(Todo todo) {
var index = todos.indexOf(todo);
todos[index].toggleCompleted();
updateDataToLocalStorage();
notifyListeners();
}
// methods for shared preferences
void initSharedPreferences() async {
sharedPreferences = await SharedPreferences.getInstance();
loadDataFromLocalStorage();
notifyListeners();
}
// Percent Method
double calcTodoPercent() {
double percent = (completedTodos.length / allTodos.length);
print('Percent : $percent');
print('Comp todos : ${completedTodos.length}');
print('UnComp todos : ${unCompletedTodos.length}');
print(percent.runtimeType);
return (completedTodos == 0 && unCompletedTodos == 0) ? 0 : percent;
}
void saveDataToLocalStorage() {
List<String>? spList =
todos.map((todo) => json.encode(todo.toJson())).toList();
sharedPreferences!.setStringList('list', spList);
}
void loadDataFromLocalStorage() {
List<String>? spList = sharedPreferences!.getStringList('list');
todos = spList!.map((item) => Todo.fromMap(json.decode(item))).toList();
}
void updateDataToLocalStorage() {
List<String>? spList =
todos.map((item) => json.encode(item.toJson())).toList();
sharedPreferences?.remove('list');
sharedPreferences!.setStringList('list', spList);
}
}
Dashboard Page button codes:
import 'package:flutter/material.dart';
import 'package:hexcolor/hexcolor.dart';
import 'package:todo_app/Widgets/Dashboard/complete_todo_list.dart';
import 'package:todo_app/Widgets/Dashboard/completed_task_info.dart';
class DashboardPage extends StatefulWidget {
const DashboardPage({Key? key}) : super(key: key);
@override
_DashboardPageState createState() => _DashboardPageState();
}
class _DashboardPageState extends State<DashboardPage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: DashboardAP(),
body: Container(
color: HexColor('#f9f6e8'),
child: Column(
children: const [
CompletedTaskInfo(),
CompleteTodoList()
],
),
),
);
}
}
AppBar DashboardAP() {
return AppBar(
leading: const Padding(
padding: EdgeInsets.only(left: 10.0, top: 15.0),
child: Icon(Icons.settings, color: Colors.black)),
//Icon(Icons.settings),
backgroundColor: HexColor('#f9f6e8'),
elevation: 0,
);
}
completed_task_ifo widget codes :
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:todo_app/provider/todos_provider.dart';
class CompletedTaskInfo extends StatefulWidget {
const CompletedTaskInfo({Key? key}) : super(key: key);
@override
_Task_InfoState createState() => _Task_InfoState();
}
class _Task_InfoState extends State<CompletedTaskInfo> {
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 24.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Padding(
padding: const EdgeInsets.only(top: 10.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'Your tasks',
style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
),
Padding(
padding: const EdgeInsets.only(top: 8.0),
child: Consumer<TodosProvider>(
builder: (context, state, child) => Text(
'You have ${state.completedTodos.length} tasks completed all time',
style: const TextStyle(
fontSize: 15,
fontWeight: FontWeight.bold,
color: Colors.grey),
),
))
],
),
),
ElevatedButton(onPressed:
() {
Provider.of<TodosProvider>(context,listen: false).checkCompletedTodos() ? print('Şuan da liste boş')
: Provider.of<TodosProvider>(context,listen: false).removeCompletedTodos();
}
, child: const Text('Clear Todos',style: TextStyle(fontSize: 10),),
style: ElevatedButton.styleFrom(shape: StadiumBorder()),
)
],
),
);
}
}
completed todo list widget codes:
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:todo_app/Models/todo.dart';
import 'package:todo_app/Pages/detail_screen.dart';
import 'package:todo_app/Widgets/Todo/todo_card.dart';
import 'package:todo_app/provider/todos_provider.dart';
import 'complete_todo_card.dart';
class CompleteTodoList extends StatefulWidget {
const CompleteTodoList({Key? key}) : super(key: key);
@override
_CompleteTodoListState createState() => _CompleteTodoListState();
}
class _CompleteTodoListState extends State<CompleteTodoList> {
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.only(top: 20.0),
child: Consumer<TodosProvider>(
builder: (context, state, child) => SizedBox(
height: MediaQuery.of(context).size.height / 1.48,
child: ListView.builder(
itemCount: state.completedTodos.length,
itemBuilder: (context, index) {
return CompleteTodoCard(
todo: state.completedTodos[index],
);
}),
),
),
);
}
}
Technically I did this but nothing changes as I can't update my master list.
- I shared the codes of the necessary pages here, but if you want to see all the codes directly, the github repo of the project: https://github.com/yagizdo/flutter_todoApp
I've been researching this all day but haven't been able to find anything and solve it. I would be very happy if you help.
Solution 1:[1]
No one answered but I just solved it. I was able to delete the completed todos in my list with the method below.
void removeCompletedTodos() {
todos.forEach((todo) {
if (todo.complete) {
var index = todos.indexOf(todo);
completedTodosList.add(todo);
notifyListeners();
}
});
todos.removeWhere((todo) => completedTodosList.contains(todo));
updateDataToLocalStorage();
notifyListeners();
}
My other codes are the same, I just created a new list to mark the completeds.
List<Todo> completedTodosList = [];
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Y?lmaz Ya??z Dokumac? |