Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Updating Firestore Document Boolean value from ListTile Flutter

I am developing an app that allows users to check kit within bags on vehicles at their base station.

I so far have the app working so that it takes the user information at log in, and shows the bags available at their particular station, in this case ‘Test Station’. I can successfully show a listView with the relevant bag information from Firestore ‘bags’ collection.

What I would like to do, is when a user taps on a listTile, to update the Boolean value for that particular bag (essentially for that particular document within the bags collection) from false to true and back again. I then want the UI to show a green or red circle Icon accordingly.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

I can only work out how to do this when I hardcode the docID for the doc I want to update the boolean of, rather than doing it dynamically dependant on which listTile the user taps on. All help to resolve this appreciated!!

so if I call this function when in the onTap:

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

 Future<void> updateBagStatus() {
    return bags
        .doc('test_bag')
        .update({'isChecked': true})
        .then((value) => print("isChecked Updated"))
        .catchError((error) => print('Failed: $error'));
  }

then I can flip the Boolean from false to true for that hardcoded bag.

and this is the rest of the code that shows how I construct the listView builder.

class HomePage extends StatefulWidget {
  const HomePage({Key? key}) : super(key: key);

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  String thisUserFirstName = '';
  String thisUserLastName = '';
  String thisUserBase = '';
  String thisStation = '';
  String thisBagChecked = '';

  CollectionReference usersCollection =
      FirebaseFirestore.instance.collection('users');
  CollectionReference bags = FirebaseFirestore.instance.collection('bags');

  Future<void> updateBagStatus() {
    return bags
        .doc('test_bag')
        .update({'isChecked': true})
        .then((value) => print("isChecked Updated"))
        .catchError((error) => print('Failed: $error'));
  }

  void _getData() async {
    User user = FirebaseAuth.instance.currentUser!;
    DocumentSnapshot thisUserSnapshot = await FirebaseFirestore.instance
        .collection('users')
        .doc(user.uid)
        .get();

    {
      setState(
        () {
          thisUserFirstName = thisUserSnapshot['first name'];
          thisUserLastName = thisUserSnapshot['last name'];
          thisUserBase = thisUserSnapshot['base station'];
        },
      );
    }
  }

  //   return StreamBuilder(
  //     stream: isCheckedSnapshot,
  //     builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
  //       if (!snapshot.hasData) {
  //         print('There is no data');
  //       }

  @override
  void initState() {
    super.initState();
    _getData();
  }

  // int selectedIndex = 0;

  @override
  Widget build(BuildContext context) {
    Stream<QuerySnapshot> bags = FirebaseFirestore.instance
        .collection("bags")
        .where("station", isEqualTo: thisUserBase)
        .snapshots();

    return Scaffold(
      backgroundColor: Colors.grey[300],
      appBar: AppBar(
        leading: Icon(Icons.settings),
        title: Text(
          'Welcome $thisUserFirstName',
          style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16),
        ),
        actions: [
          Padding(
            padding: const EdgeInsets.symmetric(horizontal: 8.0),
            child: GestureDetector(
              onTap: () {
                FirebaseAuth.instance.signOut();
              },
              child: Row(
                children: const [
                  Text('Sign Out'),
                  SizedBox(
                    width: 5,
                  ),
                  Icon(Icons.logout),
                ],
              ),
            ),
          ),
        ],
      ),
      body: Column(
        mainAxisAlignment: MainAxisAlignment.start,
        children: [
          SizedBox(height: 40),
          MyProfileRow(
            rowBanner: 'Signed in as:',
            rowIcon: Icons.person,
            userName: '$thisUserFirstName $thisUserLastName',
          ),
          SizedBox(height: 20),
          MyProfileRow(
            rowBanner: 'Base Station:',
            rowIcon: Icons.house,
            userName: thisUserBase,
          ),
          SizedBox(height: 30),
          Text("All bags at $thisUserBase"),
          SizedBox(
            height: 10,
          ),
          Expanded(
            child: StreamBuilder<QuerySnapshot>(
              stream: bags,
              builder: (
                BuildContext context,
                AsyncSnapshot<QuerySnapshot> snapshot,
              ) {
                if (snapshot.hasError) {
                  return Text('Error!');
                }

                if (snapshot.connectionState == ConnectionState.waiting) {
                  return CircularProgressIndicator();
                }

                final data = snapshot.requireData;

                return ListView.builder(
                  itemCount: data.size,
                  itemBuilder: (context, index) {
                    return Padding(
                      padding: const EdgeInsets.all(5.0),
                      child: Card(
                        elevation: 5,
                        shape: RoundedRectangleBorder(
                          borderRadius: BorderRadius.circular(8),
                        ),
                        child: ListTile(
                            title: Text('${data.docs[index]['name']}'),
                            subtitle: Text('${data.docs[index]['isChecked']}'),
                            trailing: Icon(
                              Icons.circle,
                              color: Colors.red,
                            ),
                            onTap: updateBagStatus
                            // onTap: () {
                            //   if (data.docs[index]['isChecked'] == true) {
                            //     print('isChecked = True');
                            //   }
                            //   if (data.docs[index]['isChecked'] == false) {
                            //     print('isChecked = False');
                            //   }
                            // },
                            ),
                      ),
                    );
                  },
                );
              },
            ),
          )
        ],
      ),
    );
  }
}

Click to see how I have Firestone set up:

Image of My Firestore Database:

>Solution :

Your approach is correct. You just need to pass the relevant values as function parameters as shown below:

Future<void> updateBagStatus(String docId, bool status) {
  return bags
      .doc(docId)
      .update({'isChecked': status})
      .then((value) => print("isChecked Updated"))
      .catchError((error) => print('Failed: $error'));
}
onTap: () => updateBagStatus(!data.docs[index]['isChecked'], data.docs[index].id)
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading