sp-dev-fx-controls-react icon indicating copy to clipboard operation
sp-dev-fx-controls-react copied to clipboard

TreeView - dynamic adding children, nodes always expanded

Open jimmywim opened this issue 5 years ago • 15 comments

Category

  • [ ] Enhancement

  • [ ] Bug

  • [x] Question

Version

Please specify what version of the library you are using: [1.19.0 ]

If I'm using the onExpandCollapse prop to dynamically add ITreeItem children to a node when it's expanded, then each child ITreeItem is added in an "expanded" state, so to drill further down, you need to collapse then expand in order to correctly show children.

Is there any way to add an ITreeItem with an empty children array, such that the new child is a collapsed state so that the new child item can be expanded to further retrieve children dynamically.

jimmywim avatar Aug 25 '20 14:08 jimmywim

Thank you for reporting this issue. We will be triaging your incoming issue as soon as possible.

ghost avatar Aug 25 '20 14:08 ghost

I experience the same behavior.

piteerus avatar Dec 17 '20 08:12 piteerus

@jimmywim will it be possible to you share your code? We are also trying to add children nodes on select of ITreeItem. Below is our code of TreeView control. <TreeView items={this.state.TreeLinks} defaultExpanded={false} selectionMode={TreeViewSelectionMode.Single} selectChildrenIfParentSelected={true} showCheckboxes={true} treeItemActionsDisplayMode={TreeItemActionsDisplayMode.Buttons} onSelect={this.onTreeItemSelect} onExpandCollapse={this.onTreeItemExpandCollapse} onRenderItem={this.renderCustomTreeItem} />

We are setting state value "TreeLinks" which is an array of type ITreeItem. When we click on any node, onSelect action get triigred and in that action we are not able to read state it shows undefined. Below s code of onSelect action. private onTreeItemSelect(items: ITreeItem[]) { console.log("Items selected: ", items); var someProperty = { ...this.state }; console.log(JSON.stringify(someProperty)); }

I-BhushanSalunkhe avatar Jan 15 '21 07:01 I-BhushanSalunkhe

@Bhushan12986 If your state is null you need to change onTreeItemSelect to be an arrow function..

private onTreeItemSelect = (items: ITreeItem[]) => {
    console.log("Items selected: ", items); 
    var someProperty = { ...this.state }; 
    console.log(JSON.stringify(someProperty)); 
}

jimmywim avatar Mar 29 '21 14:03 jimmywim

I decided to revisit this. I managed to get around the behaviour of the "expanded" state on adding new items with the prop

 defaultExpandedChildren={false}

on the TreeView control. However, you still need to "expand" items twice before they display. The first one appears to fetch the children and add them to the children, but it's the second click that displays them.

jimmywim avatar Mar 29 '21 15:03 jimmywim

after adding treearr.push(tree); in Else part the child nodes are binding. Expand and collapse are not working using Node-version v12.18.0 version

Please suggest on this below is the code

whole code is as below

import * as React from 'react'; import styles from './SpfxPnpTreeview.module.scss'; import { ISpfxPnpTreeviewProps } from './ISpfxPnpTreeviewProps'; import { ISpfxPnpTreeviewState } from './ISpfxPnpTreeviewState'; import { TreeView, ITreeItem, TreeViewSelectionMode, TreeItemActionsDisplayMode } from "@pnp/spfx-controls-react/lib/TreeView"; import { autobind } from 'office-ui-fabric-react/lib/Utilities';

import { sp } from "@pnp/sp"; import "@pnp/sp/webs"; import "@pnp/sp/lists"; import "@pnp/sp/items";

export default class SpfxPnpTreeview extends React.Component<ISpfxPnpTreeviewProps, ISpfxPnpTreeviewState> { constructor(props: ISpfxPnpTreeviewProps) { super(props); sp.setup({ spfxContext: this.props.context }); this.state = { TreeLinks: [] } this._getLinks(); }

private async _getLinks() { const allItems: any[] = await sp.web.lists.getByTitle("TreeLinks").items.getAll(); var treearr: ITreeItem[] = []; allItems.forEach(function (v, i) {

ManjulaMasthanvali09 avatar Feb 10 '22 16:02 ManjulaMasthanvali09

please suggest

ManjulaMasthanvali09 avatar Feb 10 '22 16:02 ManjulaMasthanvali09

I decided to revisit this. I managed to get around the behaviour of the "expanded" state on adding new items with the prop

 defaultExpandedChildren={false}

on the TreeView control. However, you still need to "expand" items twice before they display. The first one appears to fetch the children and add them to the children, but it's the second click that displays them.

+1 I'm experiencing exactly the same issue.

frankyvc avatar Apr 08 '22 12:04 frankyvc

Is there a fix for this solution already? If so, can someone please share a solution? Thanks!

frankyvc avatar Jun 22 '22 09:06 frankyvc

Hello @jimmywim,

I'm not sure if I understand your need, but I've tried something with latest version (3.15.0), like this:


private treeitems = [
    // ...
  {
    key: "R3",
    label: "Root 3",
    children: [
      {
        key: "12",
        label: "Parent 9"
      },
      {
        key: "13",
        label: "Parent 10",
        children: [
          {
            key: "gc3",
            label: "Child of Parent 10",
            children: [
              {
                key: "ggc1",
                label: "Grandchild of Parent 10"
              }
            ]
          },
        ]
      },
      {
        key: "14",
        label: "Parent 11"
      },
      {
        key: "15",
        label: "Parent 12"
      }
    ]
  }
];

public render() {

  return (
    <TreeView items={this.treeitems}
      defaultExpanded={false}
      selectionMode={TreeViewSelectionMode.Multiple}
      showCheckboxes={true}
      treeItemActionsDisplayMode={TreeItemActionsDisplayMode.ContextualMenu}
      onExpandCollapse={this.onExpandCollapseTree}
      defaultExpandedChildren={false}
      defaultExpandedKeys={this.state.treeViewSelectedKeys}
      theme={this.props.themeVariant}
    />);
}

private onExpandCollapseTree(item: ITreeItem, isExpanded: boolean) {
  console.log((isExpanded ? "item expanded: " : "item collapsed: ") + item);
  if (item.key ==="R3" && isExpanded) {
    item.children.push(...[{ key: "R1C3", label: "R1C3", children: [
      {key: "R1C3C1", label: "R1C3C1", children: []}
    ]}]);
  }
}

Which behaves like this:

spfx-controls-treeview-expand-children

Is it something like this you're trying to achieve? Of course, this needs to have the defaultExpandedChildren prop set to false first.

michaelmaillot avatar Sep 10 '23 15:09 michaelmaillot

@michaelmaillot It's been a while, in fact, it's been that long this may have already been fixed, but basically I don't (or didn't) have the full structure upfront. I need to dynamically add the children when a node is expanded because I need to fetch them from a remote API.

jimmywim avatar Sep 10 '23 15:09 jimmywim

So I think that the example above addresses your need.

If so, can I close this one or would you like to give a try first?

michaelmaillot avatar Sep 11 '23 08:09 michaelmaillot

You can likely close this. I can't remember which project this was on (as it was 3 years ago) - but if the tree re-renders sucessfully when adding to children then this should work also in an async method.

jimmywim avatar Sep 11 '23 10:09 jimmywim

I'm spoken a bit quickly, sorry. I can repro re-rendering issue when querying an API. This needs a bit of investigation in order to understand why does it behave like this and how could this be improved.

michaelmaillot avatar Sep 11 '23 17:09 michaelmaillot

Hi! I also having hard times populating the children dynamically. I understood that if I update the items (I put it into the state, and update the state when loading is done) the TreeView gets updated (quite correctly), but my problem is that because of some reason, supplying a function to the onExpandCollapse, the item will not get expanded. So, it stays there collapsed, and I do not know a way to programmatically expand it after I received the new items. Just... isn't there a way to expand an item programmatically? That would solve this problem for me. Thanks!

Gyorgy-Szy avatar Sep 19 '23 13:09 Gyorgy-Szy