Macasi
Macasi

Reputation: 3

I am trying to make a grocery app using flutter and firebase, everything is working but when I press the checkbox it Checks all of them

I made a floatingactionbutton and every time you press it it adds an item, and each item has a checkbox next to it but when I check off one item it checks all of them, I've spent a lot of time trying to figure out how to fix this but I can't. I could really use your help.

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  runApp(FireApp());
}

class FireApp extends StatefulWidget {
  @override
  _FireAppState createState() => _FireAppState();
}
    bool isChecked = false;

class _FireAppState extends State<FireApp> {
  final TextController = TextEditingController();
  @override
  Widget build(BuildContext context) {

    CollectionReference groceries =
    FirebaseFirestore.instance.collection('groceries');

    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: TextField(
            controller: TextController,
          ),
        ),
        body: Center(
          child: StreamBuilder(
            stream: groceries.orderBy('name').snapshots(),
            builder: (context, AsyncSnapshot<QuerySnapshot> snapshot) {
              return ListView(
                children: snapshot.data!.docs.map((grocery) {
                  return Center(
                    child: Row(
                      children: [
                        Container(color: Colors.red,height: 50,child: Text(grocery['name'])),
                        Checkbox(
                            materialTapTargetSize: MaterialTapTargetSize.padded,
                            value: isChecked,
                            activeColor: Colors.black,
                            checkColor: Colors.greenAccent,
                            onChanged: (bool) {
                              setState(() {
                                isChecked = !isChecked;
                              });
                            }
                        )],
                    ),
                  );
                }).toList(),
              );
            },
          ),
        ),
        floatingActionButton: FloatingActionButton(onPressed: () {
          groceries.add({
            'name': TextController.text,
          });
        },),
      ),
    );
  }
}

Upvotes: 0

Views: 132

Answers (1)

EdwynZN
EdwynZN

Reputation: 5601

You are using the same variable for all your checkboxes (isChecked) but you ougth to have one per data, you could add that attribute to your firebase document so its synced or you could create it locally but each time your stream updates you will need to compare what grocery correspond to a checkbox value which can be hard.

UPDATE

The easiest way is to have a bool parameter in your Firestore document

enter image description here

Then just push an update any time the user tap

return ListView(
            children: snapshot.data!.docs.map((grocery) {
              return Center(
                child: Row(
                  children: [
                    Container(color: Colors.red,height: 50,child: Text(grocery['name'])),
                    Checkbox(
                        materialTapTargetSize: MaterialTapTargetSize.padded,
                        value: grocery['checked'],
                        activeColor: Colors.black,
                        checkColor: Colors.greenAccent,
                        onChanged: (val) async {
                          final data = grocery.data();
                          data['checked'] = val;
                          await grocery.reference.update(data);
                        }
                    )],
                ),
              );
            }).toList(),
          );

For now this is sufficient to answer your question, you will see later that this incurs in more Firestore calls, unnecesary rebuild of all widgets in the list and so on and you will have to think another way to optimize resources, like watching the stream somewhere else to have a local List of bools that keeps in sync all values of the groceries so you only update locally with an setState and once in the cloud at the end (a save button perhaps)

Upvotes: 1

Related Questions