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

tree.treeControl.expandAll() has an error #12469

Open
docaohuynh opened this issue Aug 1, 2018 · 14 comments
Open

tree.treeControl.expandAll() has an error #12469

docaohuynh opened this issue Aug 1, 2018 · 14 comments
Labels
area: material/tree needs: discussion Further discussion with the team is needed before proceeding P3 An issue that is relevant to core functions, but does not impede progress. Important, but not urgent

Comments

@docaohuynh
Copy link

Bug

Dear team!
I has an error when I want to expand all node of Mat nested tree

ERROR TypeError: Cannot read property 'reduce' of undefined
    at NestedTreeControl.push../node_modules/@angular/cdk/esm5/tree.es5.js.NestedTreeControl.expandAll (tree.es5.js:287)
    at Object.eval [as handleEvent] (FilterViewComponent.html:18)
    at handleEvent (core.js:10050)
    at callWithDebugContext (core.js:11143)
    at Object.debugHandleEvent [as handleEvent] (core.js:10846)
    at dispatchEvent (core.js:7509)
    at core.js:7953
    at HTMLButtonElement.<anonymous> (platform-browser.js:1140)
    at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:421)
    at Object.onInvokeTask (core.js:3748)

Which versions of Angular, Material, OS, TypeScript, browsers are affected?

Angular 6.1.0
Material 6.4.1

@devversion devversion self-assigned this Aug 4, 2018
devversion added a commit to devversion/material2 that referenced this issue Aug 4, 2018
* Currently when a developer uses `NestedTreeControl` with `MatTreeNestedDataSource` and calls `treeControl.expandAll`, a runtime exception will be thrown because no data nodes are set. This issue isn't an issue if someone uses `MatTreeFlatDataSource` because the data source requires the control to be passed to the data source.

* Similarly should the `MatTreeNestedDataSource` also accept a tree control as constructor parameter. The data source should then delegate the data to the tree control in order to properly set up the tree control (similar to the flat data source)

* Also adds safety checks and throws a more user-friendly error if someone implements his own `DataSource` and does not set the data nodes on the tree control and calls `expandAll` or `getDescendants`

Fixes  angular#12469
@devversion devversion added P3 An issue that is relevant to core functions, but does not impede progress. Important, but not urgent has pr labels Aug 4, 2018
@devversion
Copy link
Member

This is not a very friendly exception. I've created a PR that should improve that.

For now though, you need to somehow set the treeControl.dataNodes property to the current data from your data source. sample code:

myDataObservable.subscribe(data => {
  this.dataSource.data = data
  this.treeControl.dataNodes = data;
});

devversion added a commit to devversion/material2 that referenced this issue Aug 7, 2018
* Currently when a developer uses `NestedTreeControl` with `MatTreeNestedDataSource` and calls `treeControl.expandAll`, a runtime exception will be thrown because no data nodes are set. This issue isn't an issue if someone uses `MatTreeFlatDataSource` because the data source requires the control to be passed to the data source.

* Similarly should the `MatTreeNestedDataSource` also accept a tree control as constructor parameter. The data source should then delegate the data to the tree control in order to properly set up the tree control (similar to the flat data source)

* Also adds safety checks and throws a more user-friendly error if someone implements his own `DataSource` and does not set the data nodes on the tree control and calls `expandAll` or `getDescendants`

Fixes angular#12469
@bhuvanp1305
Copy link

tree.treeControl.expandAll() is worked for me. but I don't understand how to expand particular node in mat tree?
@devversion Please provide any reference or solution for this.

@devversion
Copy link
Member

@bhuvanp619 Either you use the matTreeNodeToggle dirctive, or you manually find the reference to the given node and run treeControl.expand(myNode).

    const referenceToNode = database.data
      .find(d => d.filename === 'Downloads')

    this.nestedTreeControl.expand(referenceToNode);

Here is a sample stackblitz: https://stackblitz.com/edit/angular-ar8tk4

@bhuvanp1305
Copy link

@devversion I am using FlatTreeControl. will your solution work on FlatTreeControl?

@devversion
Copy link
Member

@bhuvanp619 The expand method should work similar. The solution would work even better because you can just search for the flattened data without having to walk down the tree to find nested nodes.

@bhuvanp1305
Copy link

@devversion yes you are right.
I am creating a copy move application with two tree so updated tree data is retrieved from server. So in that case when treeDataSource get new data it get collapsed. when i tried to expand new added node in tree by expand() it wont work.

@rduncan
Copy link

rduncan commented Nov 25, 2018

FWIW - in 7.0.4, tree control expands appear to work correctly for flat trees - this is because the datanodes propery of the tree control gets set by the flat data source. Nested tree controls get error with reduce being called on undefined because nothing sets the nested tree controls datanodes property.

@adamdport
Copy link

I ended up here from a stackoverflow question regarding how to preselect nodes. NestedTreeControls have an undefined dataNodes which made the answer impossible. If I recursively set dataNodes at the same time as dataSource.data as per @devversion's comment, it works fine.

Here's a reproduction of dataNodes being undefined if needed.

@emilio-martinez
Copy link
Contributor

Ran into this trying to do expandAll().

Setting the data twice as @devversion mentioned above works but is kind of an odd and error-prone API, in mo opinion. I'd expect the data source and the tree control to be more in sync rather than coordinating their data sources somewhat manually like that. The method shown above to expand a single method shown above (nestedTreeControl.expand) also is kind of odd—only because requires retroactively looking for a node to pass it to the tree control.

Perhaps the API needs some better tooling around programmatically expanding nodes? The UI part of this story is much smoother.

@rduncan
Copy link

rduncan commented Dec 4, 2018

After spending more time with trees and data tables, I think more work needs to be done on the level of abstraction. The datasource connect method needs to be informed by various controls (tree control in nested and flat trees and paging and sorting controls in the table) that may change the data needs of the tree/table. So the datasource needs to have access to these, which most naturally owned by the component in question. For one, I'm thinking of adding the datasource methods to the component under development and having it be the datasource... If I actually do that I'll post the results.

@mmalerba mmalerba added needs: discussion Further discussion with the team is needed before proceeding and removed discussion labels Mar 3, 2020
@Killerbear
Copy link

Killerbear commented Mar 2, 2022

i want to give this a little push here. I just run into this issue and noticed, this is open for 3 years.
we changed our tree from using the FlatTree to NestedTree and then the expandAll wasnt working anymore.
i hope this will be fix in the near future. At least that both variant are kind of equally useable.
Because the FlatTreeControl is working just fine but the NestedTreeControl is not.

but the workaround mentioned by devversion works for now.

@arthur-clifford
Copy link

I have a nested tree structure with a single root node.
I was able to expand everything by expanding the root node (i.e. treeControl.dataNodes[0]) and then calling expandDescendants on the same node.

Might the fix to this be an internal check on expandAll such that if it detects nested content it loops through the top level nodes and calls expand then expandDescendants on each?

// somewhere in the expandAll function for(const node of dataNodes) { treeControl.expand(node); treeControl.expandDescendants(node); }
Another option would be to allow expandDescendants() to be called without a node and in that scenario the root 'node' would be a virtual node where the children are a reference to treeControl.dataNodes.

@GuillaumeChata
Copy link

Hi,

Having the same problem for a NestedTreeControl : this.treeControl.expand(myNode) does not work.

Finally, the solution is so simple, we all never get it 😎

Just use the ChangeDetectorRef.markForCheck() after using this.treeControl.expand(this.treeControl.dataNodes[0])

So this is :

readonly treeControl = new NestedTreeControl<ModuleViewNode>(node => node.children);
 readonly dataSource = new MatTreeNestedDataSource<ModuleViewNode>();

 constructor(
   private cdr: ChangeDetectorRef
 ) {
   this.dataSource.data = TREE_DATA;
   // work arround to avoid an undefined dataNodes even after ViewInit
   this.treeControl.dataNodes = TREE_DATA;
 }

 ngOnInit() { }

 ngAfterViewInit() {
   this.treeControl.expand(this.treeControl.dataNodes[0]);
   this.cdr.markForCheck();
 }

@andrewseguin andrewseguin removed their assignment Jun 3, 2023
@kaisnb
Copy link
Contributor

kaisnb commented Feb 29, 2024

I am using CDK 17.2.1 and 11 major versions later this problem is still present. I copied the nested tree example from the docs and then tried to call this.treeControl.expandAll() but get the same error. Same as others reported it works after setting dataNodes explicitly:

this.treeControl.dataNodes = MY_DATA_NODES;
this.treeControl.expandAll();
changeDetectorRef.markForCheck();

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: material/tree needs: discussion Further discussion with the team is needed before proceeding P3 An issue that is relevant to core functions, but does not impede progress. Important, but not urgent
Projects
None yet
Development

Successfully merging a pull request may close this issue.