Angular-tree-component: Cannot set property 'scrollTop' of null

Created on 27 Feb 2017  Â·  20Comments  Â·  Source: CirclonGroup/angular-tree-component

Angular 2.4.8
Angular2-tree-component 3.1.0

Hi. After upgrading from 2.7.0 to 3.1.0 i got some issue.
When i try to do this:

this.itemsTree.treeModel.getNodeById('abc').setActiveAndVisible(true);

i got error:
"Cannot set property 'scrollTop' of null"

bug

Most helpful comment

If you need a workaround until this gets sorted out, surround the "display" request with a setTimeout(). It's working for me.

All 20 comments

I'm getting the same thing. FWIW, here's my stack trace:

Uncaught TypeError: Cannot set property 'scrollTop' of null
    at TreeVirtualScroll.exports.TreeVirtualScroll.TreeVirtualScroll.scrollIntoView (angular2-tree-component.umd.js:1208)
    at executeAction (mobx.umd.js:662)
    at TreeVirtualScroll.res (mobx.umd.js:653)
    at TreeNode.scrollIntoView (angular2-tree-component.umd.js:453)
    at TreeNode.focus (angular2-tree-component.umd.js:458)
    at TreeModel.exports.TreeModel.TreeModel.setActiveNode (angular2-tree-component.umd.js:800)
    at executeAction (mobx.umd.js:662)
    at TreeModel.res (mobx.umd.js:653)
    at TreeNode.setIsActive (angular2-tree-component.umd.js:433)
    at TreeNode.setActiveAndVisible (angular2-tree-component.umd.js:446)
    at FolderTreeComponent.setActiveAndVisible (folder-tree.component.ts:77)
    at ProjectViewComponent.doPopulateFolders (project-view.component.ts:244)

When are you calling the function? on ngOnInit?

In my case, ngInit subscribes to route.params to get the ID of the project to display. That in turn subscribes to an API request to get the folders from the project to display in the tree. When that Observable returns data, it calls the doPopulateFolders you see at the bottom of the stack. doPopulateFolders will set a folders field on the component, which serves as input to the tree nodes, Before calling setActiveAndVisible I call ChangeDetectorRef.detecthChanges() to allow the tree to populate. Perhaps that's the issue?

Same problem, but simpler: I call setActiveAndVisible() on several nodes within onInitialized().

If you need a workaround until this gets sorted out, surround the "display" request with a setTimeout(). It's working for me.

Same problem for me..
Simply put - node.setIsActive(true) gives error even after AfterViewInit.

Here's the snippet:

const node = api.getNodeById(id);
if (api.getActiveNode() !== node) { 
    node.setIsActive(true);
}

@SnackyPete
Unfortunately, that workaround didn't work for me..

Anyone figured out the source of the bug?
I'll take a look at it later this week

--

On Sun, Mar 12, 2017 at 5:42 AM, dojchek notifications@github.com wrote:

Same problem for me..
Simply put - node.setIsActive(true) gives error even after AfterViewInit.

Here's the snippet:

const node = api.getNodeById(id);
f (api.getActiveNode() !== node) {
node.setIsActive(true);
}

@SnackyPete https://github.com/SnackyPete
Unfortunately, that workaround didn't work for me..

—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
https://github.com/500tech/angular-tree-component/issues/196#issuecomment-285919952,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AA2SSlQjoXlG_BeTV8IaR5N5dWJsn_N6ks5rk2m4gaJpZM4MM8nL
.

I can create a plunker.
I have debugged it a bit - exception is thrown from TreeNode.scrollIntoView()

Same as the stacktrace @dae721 posted above.

@dae721 - Do you have this issue with older version? If not, which specific version? I will fallback to it, until this gets fixed.

It appears as though the viewport has not been created at the point that TreeNode.scrollIntoView() is called.

@dojchek I'm running 2.7 without any problems.

The problem seems to be the ngAfterViewInit function in tree-viewport.component.
In that function the call to _onVirtualScroll is made inside a setTimeout function, which makes the this._onVirtualScroll() call asynchronous.
If a parent component using TreeComponent wants to set a particular node as active in his ngOnInit function (and even in his ngAfterViewChecked function), due to the asynchronous behavior of tree-viewport's ngAfterViewInit, the viewport is not guaranteed to be initialized after ngAfterViewInit of tree-viewport is finished.
When I debugged the code and made a synchronous call to this._onVirtualScroll(), everything seemed to work.

A workaround to this problem is to get the treeComponent through:
@ViewChild(TreeComponent) treeComponent: TreeComponent;
and than to call
this.treeComponent.treeModel.virtualScroll.setNewScroll({ viewport: this.myElement.nativeElement });
on ngAfterViewChecked of the parent component.

@MarkShleifer, I can't remember why I put the timeout there, I think it was needed to catch the actual height of the container. If so, I'm not sure what the solution should be.

Fixed in 3.7.0 - use (initialized) tree event

Still happening for me with 3.7.2. Probably my situation is unique - the tree is within an *ngIf. It's initially hidden until data is retrieved from our server and a manual change detection is called. @SnackyPete's workaround to use a setTimeout works for me and I'm happy with that, but thought I'd mention it in case anyone else is still having this issue.

Appeared in version 3.7.3. Angular 4.2.4

@dae721, I also have a tree-component with an *ngIf. Everything works fine with v3.7.2, but I get the Cannot set property 'scrollTop' of null error with v3.8.0 (and [email protected]). What exactly are you wrapping in a setTimeout() to get the tree-component to work inside an *ngIf?

@dae721, I also have a tree-component with an *ngIf. Everything works fine with v3.7.2, but I get the Cannot set property 'scrollTop' of null error with v3.8.0 (and [email protected]). What exactly are you wrapping in a setTimeout() to get the tree-component to work inside an *ngIf?

@KeithGillette This function (from _our_ component) is getting wrapped in the setTimeout, (I'm leaving the millisecond parameter empty):

setActiveAndVisible(nodeId: string) {
    let node = this.treeComponent.treeModel.getNodeById(nodeId);
    if (node) {
        node.setActiveAndVisible();
    }

Just to make sure, I just upgraded to 3.8.0 and the workaround still works, although one difference from your environment is that we're still at angular 4.2.3. Hope this helps.

Thanks for the detail, @dae721. We had already used a setTimeout() when we needed to call treeModel.update() when the data for the treeView first becomes available via a network call, but that was because the treeView visibility was controlled by an *ngIf and we were accessing treeModel through @ViewChildren(TreeComponent), so the ViewChildren property wasn't always defined due to timing differences between trigger of the network data handler and the template update.

I recently tried again and updated to [email protected] and am not getting the Cannot set property 'scrollTop' of null even with no other code wrapped in `setTimeout().

I had this problem using the tree inside a dropdown from ngx-bootstrap where i used *ngIf but switching my @ViewChildren(TreeComponent) usage to (initialized) event fixed the issue for me. No need for any setTimeout()

Was this page helpful?
0 / 5 - 0 ratings

Related issues

snstarosciak picture snstarosciak  Â·  5Comments

nicolae536 picture nicolae536  Â·  5Comments

BrkCoder picture BrkCoder  Â·  4Comments

anoop-chauhan picture anoop-chauhan  Â·  3Comments

thohoh picture thohoh  Â·  5Comments