Skip to content

Commit

Permalink
feat: support load data when virtual scroll #INFR-8652 (#395)
Browse files Browse the repository at this point in the history
* feat: support load data when virtual scroll #INFR-8626

* fix: get load necessary in scrolledIndexChange

* fix: add virtualScrolledIndexChange event in gantt component

* fix: delete wrong param
  • Loading branch information
HandsomeButterball committed Jul 27, 2023
1 parent 5b86663 commit f20ad4c
Show file tree
Hide file tree
Showing 9 changed files with 96 additions and 17 deletions.
15 changes: 15 additions & 0 deletions docs/guides/basic/event.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,3 +115,18 @@ export class GanttTableDragEndedEvent<T = unknown> {
sourceParent: GanttItem<T>; // 拖动开始数据项父
}
```

# GanttVirtualScrolledIndexChangeEvent

Gantt 组件虚拟滚动视口中可见的第一个元素的索引发生变化时触发

```ts
export class GanttVirtualScrolledIndexChangeEvent {
index: number; // 视口第一个元素 index
renderedRange: {
start: number;
end: number;
}; // 当前渲染的条目范围
count: number; // 总条目数量
}
```
5 changes: 5 additions & 0 deletions example/src/app/configuration/parameters/api/zh-cn.js
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,11 @@ module.exports = [
description: `选择数据项事件`,
type: 'EventEmitter<GanttSelectedEvent>'
},
{
name: 'virtualScrolledIndexChange',
description: `虚拟滚动视口中可见的第一个元素的索引发生变化事件`,
type: 'EventEmitter<GanttVirtualScrolledIndexChangeEvent>'
},
{
name: '#group',
description: `设置分组显示模板`,
Expand Down
8 changes: 7 additions & 1 deletion example/src/app/gantt-virtual-scroll/gantt.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,13 @@
</ng-template>
</thy-header>
<thy-content>
<ngx-gantt #gantt [items]="items" [virtualScrollEnabled]="true">
<ngx-gantt
#gantt
[items]="items"
[virtualScrollEnabled]="true"
(virtualScrolledIndexChange)="virtualScrolledIndexChange($event)"
[loading]="loading"
>
<ngx-gantt-table>
<ngx-gantt-column name="标题" width="180px">
<ng-template #cell let-item="item"> {{ item.title }} </ng-template>
Expand Down
36 changes: 31 additions & 5 deletions example/src/app/gantt-virtual-scroll/gantt.component.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
import { Component, OnInit, HostBinding, ViewChild, AfterViewInit } from '@angular/core';
import { GanttItem, GanttPrintService, NgxGanttComponent } from 'ngx-gantt';
import { Component, OnInit, HostBinding, ViewChild, AfterViewInit, ChangeDetectorRef } from '@angular/core';
import { GanttItem, GanttPrintService, GanttVirtualScrolledIndexChangeEvent, NgxGanttComponent } from 'ngx-gantt';
import { delay, of } from 'rxjs';
import { randomItems, random } from '../helper';

@Component({
selector: 'app-gantt-virtual-scroll-example',
templateUrl: './gantt.component.html',
providers: [GanttPrintService]
})
export class AppGanttVirtualScrollExampleComponent implements OnInit {
items: GanttItem[] = randomItems(10000);
export class AppGanttVirtualScrollExampleComponent implements OnInit, AfterViewInit {
items: GanttItem[] = [];

@HostBinding('class.gantt-example-component') class = true;

@ViewChild('gantt') ganttComponent: NgxGanttComponent;

constructor() {}
loading = false;

constructor(private cdr: ChangeDetectorRef) {}

ngOnInit(): void {
// init items children
Expand All @@ -24,4 +27,27 @@ export class AppGanttVirtualScrollExampleComponent implements OnInit {
}
});
}

ngAfterViewInit() {
setTimeout(() => this.ganttComponent.scrollToDate(1627729997), 200);
}

virtualScrolledIndexChange(event: GanttVirtualScrolledIndexChangeEvent) {
// 检查滚动位置是否接近列表底部
if (event.renderedRange.end + 20 >= event.count) {
// 加载更多数据
if (!this.loading) {
const items = randomItems(100);
this.loading = true;
of(items)
.pipe(delay(1000))
.subscribe(() => {
console.log('loadDone');
this.loading = false;
this.items = [...this.items, ...items];
this.cdr.detectChanges();
});
}
}
}
}
2 changes: 1 addition & 1 deletion example/src/app/helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export function randomItems(length: number, parent?: GanttItem, group?: string)
const start = addDays(new Date(), random(-200, 200));
const end = addDays(start, random(0, 100));
items.push({
id: `${parent?.id || group || ''}00000${i}`,
id: `${parent?.id || group || ''}${Math.floor(Math.random() * 100000000)}`,
title: `${parent?.title || 'Task'}-${i}`,
start: getUnixTime(start),
end: getUnixTime(end),
Expand Down
1 change: 1 addition & 0 deletions example/src/styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ $primary: #6698ff;
margin: 20px;
border: 1px solid #eee;
height: calc(100vh - 95px);
overflow: auto;

.thy-layout-header {
.layout-header-title {
Expand Down
9 changes: 9 additions & 0 deletions packages/gantt/src/class/event.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,12 @@ export class GanttTableDragEnterPredicateContext<T = unknown> {
target: GanttItem<T>;
dropPosition: GanttTableDropPosition;
}

export class GanttVirtualScrolledIndexChangeEvent {
index: number;
renderedRange: {
start: number;
end: number;
};
count: number;
}
1 change: 1 addition & 0 deletions packages/gantt/src/gantt.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
[itemSize]="styles.lineHeight"
[minBufferPx]="styles.lineHeight * 10"
[maxBufferPx]="styles.lineHeight * 20"
(scrolledIndexChange)="scrolledIndexChange($event)"
>
<ng-container *cdkVirtualFor="let item of flatItems; trackBy: trackBy"></ng-container>
<div class="gantt-side" [style.width.px]="tableHeader.tableWidth + 1" [style.padding-bottom.px]="ganttRoot.horizontalScrollbarHeight">
Expand Down
36 changes: 26 additions & 10 deletions packages/gantt/src/gantt.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,15 @@ import {
import { takeUntil, take, finalize, skip } from 'rxjs/operators';
import { Observable, from } from 'rxjs';
import { GanttUpper, GANTT_UPPER_TOKEN } from './gantt-upper';
import { GanttLinkDragEvent, GanttLineClickEvent, GanttItemInternal, GanttItem, GanttSelectedEvent, GanttGroupInternal } from './class';
import {
GanttLinkDragEvent,
GanttLineClickEvent,
GanttItemInternal,
GanttItem,
GanttSelectedEvent,
GanttGroupInternal,
GanttVirtualScrolledIndexChangeEvent
} from './class';
import { NgxGanttTableColumnComponent } from './table/gantt-column.component';
import { NgxGanttTableComponent } from './table/gantt-table.component';
import { GANTT_ABSTRACT_TOKEN } from './gantt-abstract';
Expand All @@ -32,7 +40,6 @@ import { NgxGanttRootComponent } from './root.component';
import { GanttDate } from './utils/date';
import { CdkVirtualScrollViewport, ViewportRuler } from '@angular/cdk/scrolling';
import { Dictionary, keyBy, recursiveItems, uniqBy } from './utils/helpers';

@Component({
selector: 'ngx-gantt',
templateUrl: './gantt.component.html',
Expand Down Expand Up @@ -75,7 +82,7 @@ export class NgxGanttComponent extends GanttUpper implements OnInit, OnChanges,

@Input() virtualScrollEnabled = true;

@Input() loadingDelay: number = 0;
@Input() loadingDelay = 0;

@Output() linkDragStarted = new EventEmitter<GanttLinkDragEvent>();

Expand All @@ -85,6 +92,8 @@ export class NgxGanttComponent extends GanttUpper implements OnInit, OnChanges,

@Output() selectedChange = new EventEmitter<GanttSelectedEvent>();

@Output() virtualScrolledIndexChange = new EventEmitter<GanttVirtualScrolledIndexChangeEvent>();

@ContentChild(NgxGanttTableComponent) override table: NgxGanttTableComponent;

@ContentChildren(NgxGanttTableColumnComponent, { descendants: true }) columns: QueryList<NgxGanttTableColumnComponent>;
Expand All @@ -110,9 +119,9 @@ export class NgxGanttComponent extends GanttUpper implements OnInit, OnChanges,

private loadingTimer;

private rangeStart: number;
private rangeStart = 0;

private rangeEnd: number;
private rangeEnd = 0;

private flatItemsMap: Dictionary<GanttGroupInternal | GanttItemInternal>;

Expand All @@ -137,10 +146,6 @@ export class NgxGanttComponent extends GanttUpper implements OnInit, OnChanges,
// using `zone-patch-rxjs` because it'll trigger a change detection when it unsubscribes.
this.ngZone.runOutsideAngular(() => {
onStable$.pipe(takeUntil(this.unsubscribe$)).subscribe(() => {
// this.dragContainer.dragEnded.subscribe((event) => {
// this.computeTempDataRefs();
// });

this.dragContainer.linkDragStarted.pipe(takeUntil(this.unsubscribe$)).subscribe((event: GanttLinkDragEvent) => {
this.linkDragStarted.emit(event);
});
Expand Down Expand Up @@ -222,7 +227,7 @@ export class NgxGanttComponent extends GanttUpper implements OnInit, OnChanges,
this.flatItemsMap = keyBy(this.flatItems, 'id');
if (!this.virtualScrollEnabled) {
this.rangeStart = 0;
this.rangeEnd = this.flatItems.length - 1;
this.rangeEnd = this.flatItems.length;
}
}

Expand Down Expand Up @@ -307,6 +312,17 @@ export class NgxGanttComponent extends GanttUpper implements OnInit, OnChanges,
this.ganttRoot.scrollToDate(date);
}

scrolledIndexChange(index: number) {
this.virtualScrolledIndexChange.emit({
index,
renderedRange: {
start: this.rangeStart,
end: this.rangeEnd
},
count: this.flatItems.length
});
}

override expandGroups(expanded: boolean) {
this.groups.forEach((group) => {
group.setExpand(expanded);
Expand Down

0 comments on commit f20ad4c

Please sign in to comment.