Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How can I add nodes and rebuild #46

Closed
smcdonald45 opened this issue Mar 31, 2023 · 3 comments
Closed

How can I add nodes and rebuild #46

smcdonald45 opened this issue Mar 31, 2023 · 3 comments
Labels
question Further information is requested

Comments

@smcdonald45
Copy link

I try to use your tree using blocs. Is it possible, to rebuild nodes after new children have been added to nodes?

Here is a part of my test code:

    return BlocProvider(
      create: (context) => DirectoryTreeBloc()
        ..add(
          DirectoriesRequestedEvent(),
        ),
      child: BlocBuilder<DirectoryTreeBloc, DirectoryTreeState>(
        builder: (context, state) {
          final rootNode = state.rootNode;

          final treeController = TreeController<TreeNodeData>(
            roots: [rootNode],
            childrenProvider: (node) {
              return node.children ?? const [];
            },
          );

          return Material(
            child: Column(
              children: [
                Expanded(
                  child: AnimatedTreeView(
                    treeController: treeController,
                    nodeBuilder: (context, entry) {
                      return TreeIndentation(
                        entry: entry,
                        child: Row(
                          children: [
                            FolderButton(
                              splashRadius: 20,
                              isOpen: treeController.getExpansionState(
                                entry.node,
                              ),
                              onPressed: () => treeController.toggleExpansion(
                                entry.node,
                              ),
                            ),
                            Text(entry.node.title),
                          ],
                        ),
                      );
                    },
                  ),
                ),

After new nodes are found in the repository a new state is emitted which results in rebuild. The new node appears after I toggle state of the parent or click a sibling node. But what must I change for get the new node appearing after rebuild?

I hope it can be done as I do not want to use any other tree..

@baumths baumths added the question Further information is requested label Mar 31, 2023
@baumths
Copy link
Owner

baumths commented Mar 31, 2023

Hey @smcdonald45 thank you for using the package!

The first thing I see that I must point out is that you are creating a new TreeController each time the DirectoryTreeBloc emits a new state. The controller should live in a StatefulWidget or in your dependency injection tool (e.g., Provider).

With the TreeController lifted out you could add a BlocListener on your DirectoryTreeBloc to update the TreeController.roots variable when a new root is emitted (the roots setter of the controller will rebuild the tree implicitly for you).

Other than that, the snippet of code that you shared didn't include your TreeNodeData neither the function that is finding and populating the tree nodes so I don't know how to help you in that regard.

Everytime the tree changes in any way that is not a call to a method on TreeController, you must call TreeController.rebuild() to make sure the controller notifies the listening tree views that the tree structure changed and they should update their values (the flat tree).

Try the above and let me know if it helped!

remember to dispose() your TreeController 😉

@smcdonald45
Copy link
Author

Thx a lot. I will try this out. Im quite new to flutter, dart and bloc but it makes really fun ;D

@smcdonald45
Copy link
Author

Wow, that was easy ;D Thx a lot. Your tree works really great with a really low amont of code!!

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_fancy_tree_view/flutter_fancy_tree_view.dart';
import 'package:picmac/tree/bloc/directory_tree_bloc.dart';

class TreeNodeData {
  TreeNodeData(this.path, this.title, {this.children});

  final String path;
  final String title;
  List<TreeNodeData>? children;
}

class DirectoryTreeView extends StatefulWidget {
  const DirectoryTreeView({super.key});

  @override
  State<DirectoryTreeView> createState() => _DirectoryTreeViewState();
}

class _DirectoryTreeViewState extends State<DirectoryTreeView> {
  late final TreeController<TreeNodeData> _treeController;

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

    // build initial empty tree controller. will get some roots later by the bloc
    _treeController = TreeController(
      roots: <TreeNodeData>[],
      childrenProvider: (node) => node.children ?? <TreeNodeData>[],
    );
  }

  @override
  Widget build(BuildContext context) {
    // the bloc listener only listen to refreshed states emitted by the bloc if a new directory
    // appears in the path somewhere
    return BlocListener<DirectoryTreeBloc, DirectoryTreeState>(
      listenWhen: (previous, current) {
        return current.status == DirectoryTreeStatus.refreshed;
      },
      listener: (context, state) {
        // update the complete tree
        _treeController.roots = [state.rootNode];
      },

      // as soon as the directories are loaded the success state is emitted and we can build
      // the directory tree with the final tree data
      child: BlocBuilder<DirectoryTreeBloc, DirectoryTreeState>(
        buildWhen: (previous, current) {
          return current.status == DirectoryTreeStatus.success;
        },
        builder: (context, state) {
          _treeController.roots = [state.rootNode];

          return Material(
            child: Column(
              children: [
                Expanded(
                  child: AnimatedTreeView(
                    treeController: _treeController,
                    nodeBuilder: (context, entry) {
                      return TreeIndentation(
                        entry: entry,
                        child: Row(
                          children: [
                            FolderButton(
                              splashRadius: 20,
                              isOpen: _treeController.getExpansionState(
                                entry.node,
                              ),
                              onPressed: () => _treeController.toggleExpansion(
                                entry.node,
                              ),
                            ),
                            Text(entry.node.title),
                          ],
                        ),
                      );
                    },
                  ),
                ),
                OutlinedButton(
                  onPressed: () => context.read<DirectoryTreeBloc>().add(
                        SimulateDirectoriesChangedEvent(),
                      ),
                  child: const Text('foo'),
                ),
              ],
            ),
          );
        },
      ),
    );
  }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants