Skip to content

Commit

Permalink
perf: do not run change detection when bar handles are clicked
Browse files Browse the repository at this point in the history
  • Loading branch information
arturovt authored and walkerkay committed Mar 25, 2022
1 parent 187f506 commit 9d219cc
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 11 deletions.
4 changes: 2 additions & 2 deletions packages/gantt/src/components/bar/bar.component.html
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<div class="gantt-bar-layer">
<div *ngIf="item.draggable && ganttUpper.draggable" class="drag-handles">
<ng-container>
<span class="handle" (mousedown)="stopPropagation($event)"></span>
<span class="handle" (mousedown)="stopPropagation($event)"></span>
<span class="handle" #handle></span>
<span class="handle" #handle></span>
</ng-container>
</div>
<div *ngIf="item.linkable && ganttUpper.linkable" class="link-handles">
Expand Down
38 changes: 31 additions & 7 deletions packages/gantt/src/components/bar/bar.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,13 @@ import {
ViewChild,
Output,
EventEmitter,
AfterViewInit
AfterViewInit,
ViewChildren,
QueryList,
NgZone
} from '@angular/core';
import { takeUntil } from 'rxjs/operators';
import { fromEvent, merge, Observable } from 'rxjs';
import { startWith, switchMap, takeUntil } from 'rxjs/operators';
import { GanttBarDrag } from './bar-drag';
import { hexToRgb } from '../../utils/helpers';
import { GanttDragContainer } from '../../gantt-drag-container';
Expand All @@ -36,13 +40,16 @@ export class NgxGanttBarComponent extends GanttItemUpper implements OnInit, Afte

@HostBinding('class.gantt-bar') ganttItemClass = true;

@ViewChildren('handle') handles: QueryList<ElementRef<HTMLElement>>;

color = 'red';

constructor(
private dragContainer: GanttDragContainer,
private drag: GanttBarDrag,
elementRef: ElementRef<HTMLDivElement>,
@Inject(GANTT_UPPER_TOKEN) public ganttUpper: GanttUpper
@Inject(GANTT_UPPER_TOKEN) public ganttUpper: GanttUpper,
private ngZone: NgZone
) {
super(elementRef, ganttUpper);
}
Expand All @@ -57,6 +64,27 @@ export class NgxGanttBarComponent extends GanttItemUpper implements OnInit, Afte
ngAfterViewInit() {
this.drag.createDrags(this.elementRef, this.item, this.ganttUpper);
this.setContentBackground();

this.handles.changes
.pipe(
startWith(this.handles),
switchMap(
() =>
// Note: we need to explicitly subscribe outside of the Angular zone since `addEventListener`
// is called when the `fromEvent` is subscribed.
new Observable<Event>((subscriber) =>
this.ngZone.runOutsideAngular(() =>
merge(...this.handles.toArray().map((handle) => fromEvent(handle.nativeElement, 'mousedown'))).subscribe(
subscriber
)
)
)
),
takeUntil(this.unsubscribe$)
)
.subscribe((event) => {
event.stopPropagation();
});
}

ngOnChanges(): void {
Expand Down Expand Up @@ -97,10 +125,6 @@ export class NgxGanttBarComponent extends GanttItemUpper implements OnInit, Afte
}
}

stopPropagation(event: Event) {
event.stopPropagation();
}

ngOnDestroy() {
super.onDestroy();
}
Expand Down
16 changes: 14 additions & 2 deletions packages/gantt/src/components/bar/test/bar.drag.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { CommonModule } from '@angular/common';
import { Component, DebugElement, Directive } from '@angular/core';
import { ComponentFixture, TestBed, fakeAsync, tick, flush } from '@angular/core/testing';
import { ApplicationRef, Component, DebugElement } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { GanttDragEvent, GanttLinkDragEvent } from '../../../class';
import { NgxGanttComponent } from '../../../gantt.component';
Expand Down Expand Up @@ -193,4 +193,16 @@ describe('bar-drag', () => {
const lastHandleElement = bar.queryAll(By.css('.link-handles .handle'))[1].nativeElement;
linkDragEvent(fixture, lastHandleElement);
});

it('should not run change detection when the `mousedown` is dispatched on the handle', () => {
const appRef = TestBed.inject(ApplicationRef);
spyOn(appRef, 'tick');
const bar = fixture.debugElement.queryAll(By.directive(NgxGanttBarComponent))[0];
const firstHandleElement = bar.queryAll(By.css('.drag-handles .handle'))[0].nativeElement;
const event = new Event('mousedown');
spyOn(event, 'stopPropagation').and.callThrough();
firstHandleElement.dispatchEvent(event);
expect(appRef.tick).not.toHaveBeenCalled();
expect(event.stopPropagation).toHaveBeenCalled();
});
});

0 comments on commit 9d219cc

Please sign in to comment.