Search code examples
flutterfirebaseredux-firestore

How to make animated tree view with data from sub-collection firestore


This is the my treeview page Scaffold code sample. I used Animated tree view class

 import 'package:animated_tree_view/animated_tree_view.dart';
    
// Widget build
    return Scaffold(
            key: _scaffoldKey,
            appBar: AppBar(
              title: Text(widget.title),
            ),
            body: CustomScrollView(
              controller: scrollController,
              slivers: [
                SliverToBoxAdapter(
                  child: Padding(
                      padding: const EdgeInsets.only(
                          top: 12.0, left: 12, right: 30, bottom: 12),
                      child: Align(
                        alignment: Alignment.topLeft,
                        child: SizedBox(
                          width: 200,
                          height: 40,
                          child: ElevatedButton(
                            child: const Text("Add main activity"),
                            style: ElevatedButton.styleFrom(
                                backgroundColor: Theme.of(context).primaryColor,
                                textStyle: const TextStyle(color: Colors.white),
                                shape: RoundedRectangleBorder(
                                    borderRadius: BorderRadius.circular(5))),
                            onPressed: () {
                              // simpleTree.add(TreeNode());
                              Navigator.of(context)
                                  .push(MaterialPageRoute(
                                      builder: (context) => const ActivityAdd(
                                          title: 'Add Activity', selfId: 'root')))
                                  .then((val) => {
                                        debugPrint(val),
                                        val ? _getRequests() : null
                                      });
                            },
                          ),
                        ),
                      )),
                ),
                SliverTreeView.simple(
                  tree: simpleTree,
                  expansionBehavior: ExpansionBehavior.collapseOthers,
                  showRootNode: false,
                  key: _simpleTreeKey,
                  scrollController: scrollController,
                  builder: (context, node) => Card(
                      child: node.isRoot
                          ? buildRootItem(node)
                          : buildListItem(node)),
                ),
              ],
            ));
      }

If you have any experience animated tree view with firebase data. Finally I want to auto update when user add a new tree node to database. I find some ways to display tree view but it is not work to real time. Please help me.


Solution

  • I solved this problem myself.

    Final code as follows

    In activity_model.dart

    TreeNode simpleTree = TreeNode.root();
      Future<TreeNode> getTree() async {
        simpleTree = TreeNode.root();
        final snapshot =
            await FirebaseFirestore.instance.collection(C_ACTIVITIES).get();
        snapshot.docs.map((doc) => {_buildNode(doc)}).toList();
        return simpleTree;
      }
    
      Future<void> _buildNode(DocumentSnapshot doc) async {
        simpleTree.add(TreeNode(key: doc.id.toString(), data: doc.data()!));
        _buildChildNode(doc, doc.id.toString());
      }
    
      Future<void> _buildChildNode(DocumentSnapshot doc, String pathtext) async {
        final childrenRef = await doc.reference.collection('activity_child').get();
        pathtext += "." + doc.id.toString();
        if (childrenRef.docs.isNotEmpty) {
          childrenRef.docs
              .map((doc) => {
                    simpleTree
                        .elementAt(pathtext)
                        .add(TreeNode(key: doc.id.toString(), data: doc.data())),
                    _buildChildNode(doc, pathtext),
                  })
              .toList();
        }
      }
    

    In activity_page.dart

    final Future<TreeNode> futureTree = Future<TreeNode>.delayed(
        const Duration(milliseconds: 1000),
        () => ActivityModel().getTree(),
      );
    
    
    Scaffold(
            key: _scaffoldKey,
            appBar: AppBar(
              title: Text(widget.title),
            ),
            body: FutureBuilder<TreeNode>(
                future: futureTree,
                builder: (BuildContext context, AsyncSnapshot<TreeNode> snapshot) {
                  if (snapshot.hasData) {
                    return CustomScrollView(
                      controller: scrollController,
                      slivers: [
                        SliverToBoxAdapter(
                          child: Padding(
                              padding: const EdgeInsets.only(
                                  top: 12.0, left: 12, right: 30, bottom: 12),
                              child: Align(
                                alignment: Alignment.topLeft,
                                child: SizedBox(
                                  width: 200,
                                  height: 40,
                                  child: ElevatedButton(
                                    child: const Text("Add main activity"),
                                    style: ElevatedButton.styleFrom(
                                        backgroundColor:
                                            Theme.of(context).primaryColor,
                                        textStyle:
                                            const TextStyle(color: Colors.white),
                                        shape: RoundedRectangleBorder(
                                            borderRadius:
                                                BorderRadius.circular(5))),
                                    onPressed: () {
                                      // simpleTree.add(TreeNode());
                                      Navigator.of(context)
                                          .push(MaterialPageRoute(
                                              builder: (context) =>
                                                  const ActivityAdd(
                                                      title: 'Add Activity',
                                                      selfId: 'root')))
                                          .then((val) => {
                                                val == 'success'
                                                    ? _getRequests()
                                                    : null
                                              });
                                    },
                                  ),
                                ),
                              )),
                        ),
                        SliverTreeView.simple(
                            tree: simpleTree,
                            expansionBehavior: ExpansionBehavior.collapseOthers,
                            showRootNode: false,
                            key: _simpleTreeKey,
                            onItemTap: (value) => {},
                            scrollController: scrollController,
                            onTreeReady: (controller) => {debugPrint("Loaded")},
                            builder: (context, node) {
                              return node.isRoot
                                  ? buildRootItem(node)
                                  : buildListItem(node);
                            }),
                      ],
                    );
                  } else if (snapshot.hasError) {
                    return Text('Error: ${snapshot.error}');
                  } else {
                    return Center(
                      child: SizedBox(
                        width: 60,
                        height: 60,
                        child: CircularProgressIndicator(),
                      ),
                    );
                  }
                }));
      }
    }
    

    It was working well now.