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

Show/hide leaf nodes by outer prop #95

Open
orelHAnyvision opened this issue Feb 16, 2023 · 3 comments
Open

Show/hide leaf nodes by outer prop #95

orelHAnyvision opened this issue Feb 16, 2023 · 3 comments

Comments

@orelHAnyvision
Copy link

hi,
Im trying to enable the functionality to show and hide the leaf elements by clicking on a button outside of the tree,
currently even if I hide the rendered element its height is still there so I have gaps where the leaf nodes were displayed.
is there any way to do it with the react-vtree?

@gregjoeval
Copy link

@orelHAnyvision, does the answer to #65 help you at all?

@orelHAnyvision
Copy link
Author

@gregjoeval nope

@gregjoeval
Copy link

gregjoeval commented Mar 22, 2023

@orelHAnyvision,

Apologies if you don't find exactly what you're looking for. It's difficult to infer the specifics of the feature you're trying to create, and some creative problem solving on your part might be necessary. I am not a maintainer of this library, I am just a community member trying to help people solve issues with a library.

In order to "show/hide" the elements with this library you need to recompute the tree and set isOpen to true or false, respectively, for each node. It seems that you want to show/hide all leaf elements (i.e. all elements not at "depth" zero). Assuming you have multiple root nodes you can create a function to recompute the tree setting the root nodes to open and the nodes of their subtrees to not open. If you wanted to provide business logic to figure out of a leaf should be open or not you would need to add properties to the node's public data and then use that to determine if the node should be open or not (see Option B or C).

I will do my best to create an example:

import {
  NodeData,
  NodePublicState,
  OpennessStateUpdateRules,
} from 'react-vtree/dist/es/Tree';

// Types assumed for this example

interface ITreeWalkerData extends NodeData {
  displayName: string;
  depth: number;
}

type RecomputeTreeKeyValuePair = [
  string,
  (
    | OpennessStateUpdateRules<
        ITreeWalkerData,
        NodePublicState<ITreeWalkerData>
      >
    | boolean
  )
];

// for the brevity of this example I will assume the tree is of this structure
/**
        ProjectA/
	  ├── behavior.min.js
	  ├── styles.css
	  ├── vendor/lib.js
        ProjectB/
	  ├── behavior.min.js
	  ├── styles.css
	  ├── vendor/lib.js
	  ├── perfect-scrollbar/
	  |  ├── jquery.min.js
	  |  ├── jquery.mousewheel.js
  	  |  ├── perfect-scrollbar.js
	  |  └── perfect-scrollbar.css
	  ├── examples/
	  |  └── ...
**/

in your Tree component:

  const ref = useRef<FixedSizeTree<ITreeWalkerData>>(null);

  const [leafOpenness, setLeafOpenness] = useState(true)

  const toggleLeafOpenness = useCallback(async (isOpen: boolean) => {
    await ref.current?.recomputeTree(
      Object.fromEntries(
        // Note: This is for a tree with multiple root nodes
        rootNodes.map(
          (m): RecomputeTreeKeyValuePair => [
            // createNodeId is a custom function to construct and ensure a unique id per node
            createNodeId(m.key),
            {
              open: true, // because you said that you wanted only the leafs to close
              subtreeCallback: (node) => {
                /** 
                In here you can use node to look at the date and specific 
                further logic that determines the open state of each node. 

                Since you said that you only wanted to show/hide the leaf nodes, 
                I assumed that you have multiple root nodes and can just set the 
                open state of each leaf of those root nodes directly.

                If you wanted to prevent the user from expanding the tree by 
                clicking on the root nodes then you might want to hide or disable 
                their ability to do so based on `leafOpenness`
                **/ 

                // Option A:
                // This will toggle the openness of all nodes except for ProjectA and ProjectB
                node.isOpen = isOpen; // NOTE: this is permitted by the library and is faster than using setOpen

                // or Option B:
                // This will toggle the openness of all nodes except for ProjectA and ProjectB and their direct nodes
                if (node.data.depth > 1) {
                  node.isOpen = isOpen;
                }

                // or Option C:
                // This will toggle the openness of all nodes except for ProjectA and ProjectB and any nodes that end with '.js'
                if (node.data.displayName.endsWith('.js')) {
                  node.isOpen = isOpen;
                }
              },
            },
          ]
        )
      )
    );

    setLeafOpenness(isOpen)
  }, [rootNodes, setLeafOpenness]);

  return (
    <div>
      <button onClick={() => toggleLeafOpenness(!leafOpenness)}>{leafOpenness ? "Hide Leafs" : "Show Leafs"}</button>
      <FixedSizeTree
        ...
        ref={ref}
      >
        ...
      </FixedSizeTree>
    </div>
  )

I hope that this helps! Please let me know if you have any questions about my example.

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

No branches or pull requests

2 participants