Skip to content

Commit ecf9fb6

Browse files
committed
Added scrollContainer option to allow scrolling in external container
1 parent cf83d72 commit ecf9fb6

File tree

8 files changed

+75
-8
lines changed

8 files changed

+75
-8
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<a name="7.2.0"></a>
22
# 7.2.0 (2018-xx-xx)
33
* Added nodeActivate and nodeDeactivate events for IE11 - issue #387
4+
* Added scrollContainer option to allow scrolling in external container - issue #92
45

56
<a name="7.1.0"></a>
67
# 7.1.0 (2018-24-03)

example/cli/src/app/app-routing.module.ts

+5
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import { DragComponent } from './drag/drag.component';
1515
import { VirtualscrollComponent } from './virtualscroll/virtualscroll.component';
1616
import { ApiComponent } from './api/api.component';
1717
import { ActionsComponent } from './actions/actions.component';
18+
import { ScrollContainerComponent } from './scrollcontainer/scrollcontainer.component';
1819

1920
const routes: Routes = [
2021
{
@@ -72,6 +73,10 @@ const routes: Routes = [
7273
{
7374
path: 'actions',
7475
component: ActionsComponent
76+
},
77+
{
78+
path: 'scroll-container',
79+
component: ScrollContainerComponent
7580
}
7681
];
7782

example/cli/src/app/app.module.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import { DragComponent } from './drag/drag.component';
2020
import { VirtualscrollComponent } from './virtualscroll/virtualscroll.component';
2121
import { ApiComponent } from './api/api.component';
2222
import { ActionsComponent } from './actions/actions.component';
23+
import { ScrollContainerComponent } from './scrollcontainer/scrollcontainer.component';
2324

2425
@NgModule({
2526
declarations: [
@@ -37,7 +38,8 @@ import { ActionsComponent } from './actions/actions.component';
3738
DragComponent,
3839
VirtualscrollComponent,
3940
ApiComponent,
40-
ActionsComponent
41+
ActionsComponent,
42+
ScrollContainerComponent
4143
],
4244
imports: [
4345
BrowserModule,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { Component, Input, OnInit } from '@angular/core';
2+
import { TreeNode, TreeModel, TREE_ACTIONS, KEYS, IActionMapping, ITreeOptions } from 'angular-tree-component';
3+
4+
@Component({
5+
selector: 'app-scrollcontainer',
6+
styles: [
7+
],
8+
template: `
9+
<div style="height: 300px; width: 200px;border: 1px solid grey">Padding</div>
10+
<div>
11+
<tree-root
12+
#tree
13+
[nodes]="nodes"
14+
[options]="options"
15+
[focused]="true"
16+
></tree-root>
17+
</div>
18+
`
19+
})
20+
export class ScrollContainerComponent implements OnInit {
21+
nodes: any[] = [];
22+
options: ITreeOptions = {
23+
scrollContainer: <HTMLElement>document.body.parentElement
24+
};
25+
constructor() {
26+
}
27+
ngOnInit() {
28+
for (let i = 0; i < 200; i++) {
29+
this.nodes.push({
30+
name: `rootDynamic${i}`,
31+
subTitle: `root created dynamically ${i}`
32+
});
33+
}
34+
}
35+
36+
}

example/cli/src/styles.css

+3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
/* You can add global styles to this file, and also import other style files */
22
@import '~angular-tree-component/dist/angular-tree-component.css';
3+
html, body {
4+
height: 100%;
5+
}
36
.reverse tree-node-expander {
47
order: 0;
58
}

lib/defs/api.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,11 @@ export interface ITreeOptions {
261261
/**
262262
* Whether to use master checkboxes mechanism if the useCheckbox is set to true
263263
*/
264-
useTriState?: boolean;
264+
useTriState?: boolean
265+
/**
266+
* The HTML element that is the scroll container for the tree. The default behaviour is to wrap the tree with a container that has overflow: hidden, and then the scrolling container is the viewport inside the tree component
267+
*/
268+
scrollContainer?: HTMLElement;
265269
}
266270

267271
export interface ITreeNode {

lib/models/tree-options.model.ts

+1
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ export class TreeOptions {
9494
get rootId(): any {return this.options.rootId; }
9595
get useCheckbox(): boolean { return this.options.useCheckbox; }
9696
get useTriState(): boolean { return this.options.useTriState === undefined ? true : this.options.useTriState; }
97+
get scrollContainer(): HTMLElement { return this.options.scrollContainer; }
9798
actionMapping: IActionMapping;
9899

99100
constructor(private options: ITreeOptions = {}) {

lib/models/tree-virtual-scroll.model.ts

+21-6
Original file line numberDiff line numberDiff line change
@@ -92,15 +92,30 @@ export class TreeVirtualScroll {
9292
}
9393

9494
@action scrollIntoView(node, force, scrollToMiddle = true) {
95-
if (force || // force scroll to node
96-
node.position < this.y || // node is above viewport
97-
node.position + node.getSelfHeight() > this.y + this.viewportHeight) { // node is below viewport
98-
if (this.viewport) {
99-
this.viewport.scrollTop = scrollToMiddle ?
95+
if (node.options.scrollContainer) {
96+
const scrollContainer = node.options.scrollContainer;
97+
const scrollContainerHeight = scrollContainer.getBoundingClientRect().height;
98+
const scrollContainerTop = scrollContainer.getBoundingClientRect().top;
99+
const nodeTop = this.viewport.getBoundingClientRect().top + node.position - scrollContainerTop;
100+
101+
if (force || // force scroll to node
102+
nodeTop < scrollContainer.scrollTop || // node is above scroll container
103+
nodeTop + node.getSelfHeight() > scrollContainer.scrollTop + scrollContainerHeight) { // node is below container
104+
scrollContainer.scrollTop = scrollToMiddle ?
105+
nodeTop - scrollContainerHeight / 2 : // scroll to middle
106+
nodeTop; // scroll to start
107+
}
108+
} else {
109+
if (force || // force scroll to node
110+
node.position < this.y || // node is above viewport
111+
node.position + node.getSelfHeight() > this.y + this.viewportHeight) { // node is below viewport
112+
if (this.viewport) {
113+
this.viewport.scrollTop = scrollToMiddle ?
100114
node.position - this.viewportHeight / 2 : // scroll to middle
101115
node.position; // scroll to start
102116

103-
this._setYBlocks(Math.floor(this.viewport.scrollTop / Y_EPSILON));
117+
this._setYBlocks(Math.floor(this.viewport.scrollTop / Y_EPSILON));
118+
}
104119
}
105120
}
106121
}

0 commit comments

Comments
 (0)