简体   繁体   English

从 ListTile Flutter 更新 Firestore 文档 Boolean 值

[英]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.我可以成功地显示一个 listView,其中包含来自 Firestore“包”集合的相关包信息。

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.我想做的是,当用户点击 listTile 时,将该特定包(基本上是包集合中的特定文档)的 Boolean 值从 false 更新为 true,然后再返回。 I then want the UI to show a green or red circle Icon accordingly.然后我希望 UI 相应地显示一个绿色或红色圆圈图标。

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.当我对要更新 boolean 的文档的 docID 进行硬编码时,我只能弄清楚如何执行此操作,而不是根据用户点击的 listTile 动态执行此操作。 All help to resolve this appreciated!!所有帮助解决这个赞赏!

so if I call this function when in the onTap:所以如果我在 onTap 中调用这个 function:

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.然后我可以将那个硬编码包的 Boolean 从 false 翻转为 true。

and this is the rest of the code that shows how I construct the listView builder.这是显示我如何构建 listView 生成器的代码的 rest。

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:单击以查看我如何设置 Firestone:

Image of My Firestore Database:我的 Firestore 数据库的图像:

Your approach is correct.你的做法是正确的。 You just need to pass the relevant values as function parameters as shown below:您只需将相关值作为 function 参数传递,如下所示:

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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM