Skip to content

Commit 0e6607e

Browse files
authored
Merge pull request #5464 from IgniteUI/dpetev/ios-grid-edit-8-1
fix(grids): handle double tap to allow editing on iOS #2538
2 parents f030eb2 + 83040e3 commit 0e6607e

File tree

5 files changed

+63
-12
lines changed

5 files changed

+63
-12
lines changed

projects/igniteui-angular/src/lib/core/touch.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,11 @@ export class HammerGesturesManager {
2020
inputClass: Hammer.TouchInput,
2121
recognizers: [
2222
[ Hammer.Pan, { threshold: 0 } ],
23-
[ Hammer.Pinch, { enable: true } ],
24-
[ Hammer.Rotate, { enable: true } ],
2523
[ Hammer.Swipe, {
2624
direction: Hammer.DIRECTION_HORIZONTAL
27-
}]
25+
}],
26+
[Hammer.Tap],
27+
[Hammer.Tap, { event: 'doubletap', taps: 2 }, ['tap']]
2828
]
2929
};
3030

@@ -44,14 +44,14 @@ export class HammerGesturesManager {
4444
public addEventListener(element: HTMLElement,
4545
eventName: string,
4646
eventHandler: (eventObj) => void,
47-
options: object = null): () => void {
47+
options: HammerOptions = null): () => void {
4848

4949
// Creating the manager bind events, must be done outside of angular
5050
return this._zone.runOutsideAngular(() => {
5151
let mc: HammerManager = this.getManagerForElement(element);
5252
if (mc === null) {
5353
// new Hammer is a shortcut for Manager with defaults
54-
mc = new Hammer(element, this.hammerOptions);
54+
mc = new Hammer(element, Object.assign(this.hammerOptions, options));
5555
this.addManagerForElement(element, mc);
5656
}
5757
const handler = (eventObj) => { this._zone.run(() => { eventHandler(eventObj); }); };

projects/igniteui-angular/src/lib/grids/cell.component.ts

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import { State } from '../services/index';
2323
import { IgxGridBaseComponent, IGridEditEventArgs, IGridDataBindable } from './grid-base.component';
2424
import { IgxGridSelectionService, ISelectionNode, IgxGridCRUDService } from '../core/grid-selection';
2525
import { DeprecateProperty } from '../core/deprecateDecorators';
26+
import { HammerGesturesManager } from '../core/touch';
2627

2728
/**
2829
* Providing reference to `IgxGridCellComponent`:
@@ -40,7 +41,8 @@ import { DeprecateProperty } from '../core/deprecateDecorators';
4041
@Component({
4142
changeDetection: ChangeDetectionStrategy.OnPush,
4243
selector: 'igx-grid-cell',
43-
templateUrl: './cell.component.html'
44+
templateUrl: './cell.component.html',
45+
providers: [HammerGesturesManager]
4446
})
4547
export class IgxGridCellComponent implements OnInit, OnChanges, OnDestroy {
4648
private _vIndex = -1;
@@ -530,7 +532,8 @@ export class IgxGridCellComponent implements OnInit, OnChanges, OnDestroy {
530532
public selection: IgxSelectionAPIService,
531533
public cdr: ChangeDetectorRef,
532534
private element: ElementRef,
533-
protected zone: NgZone) { }
535+
protected zone: NgZone,
536+
private touchManager: HammerGesturesManager) { }
534537

535538

536539
/**
@@ -552,6 +555,9 @@ export class IgxGridCellComponent implements OnInit, OnChanges, OnDestroy {
552555
this.nativeElement.addEventListener('compositionend', this.compositionEndHandler);
553556
}
554557
});
558+
this.touchManager.addEventListener(this.nativeElement, 'doubletap', this.onDoubleClick, {
559+
cssProps: { } /* don't disable user-select, etc */
560+
} as HammerOptions);
555561
}
556562

557563
/**
@@ -569,6 +575,7 @@ export class IgxGridCellComponent implements OnInit, OnChanges, OnDestroy {
569575
this.nativeElement.removeEventListener('compositionend', this.compositionEndHandler);
570576
}
571577
});
578+
this.touchManager.destroy();
572579
}
573580

574581
/**
@@ -716,7 +723,11 @@ export class IgxGridCellComponent implements OnInit, OnChanges, OnDestroy {
716723
* @internal
717724
*/
718725
@HostListener('dblclick', ['$event'])
719-
public onDoubleClick(event: MouseEvent) {
726+
public onDoubleClick = (event: MouseEvent| HammerInput) => {
727+
if (event.type === 'doubletap') {
728+
// prevent double-tap to zoom on iOS
729+
event.preventDefault();
730+
}
720731
if (this.editable && !this.editMode && !this.row.deleted) {
721732
this.crudService.begin(this);
722733
}

projects/igniteui-angular/src/lib/grids/grid/cell.spec.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { UIInteractions, wait } from '../../test-utils/ui-interactions.spec';
88
import { configureTestSuite } from '../../test-utils/configure-suite';
99
import { IgxStringFilteringOperand } from '../../data-operations/filtering-condition';
1010
import { SampleTestData } from '../../test-utils/sample-test-data.spec';
11+
import { HammerGesturesManager } from '../../core/touch';
1112

1213
const DEBOUNCETIME = 30;
1314

@@ -171,6 +172,7 @@ describe('IgxGrid - Cell component', () => {
171172

172173
spyOn(grid.onDoubleClick, 'emit').and.callThrough();
173174
const event = new Event('dblclick');
175+
spyOn(event, 'preventDefault');
174176
cellElem.nativeElement.dispatchEvent(event);
175177
const args: IGridCellEventArgs = {
176178
cell: firstCell,
@@ -179,6 +181,38 @@ describe('IgxGrid - Cell component', () => {
179181

180182
fix.detectChanges();
181183

184+
expect(event.preventDefault).not.toHaveBeenCalled();
185+
expect(grid.onDoubleClick.emit).toHaveBeenCalledWith(args);
186+
expect(firstCell).toBe(fix.componentInstance.clickedCell);
187+
});
188+
189+
it('Should handle doubletap, trigger onDoubleClick event', () => {
190+
const addListenerSpy = spyOn(HammerGesturesManager.prototype, 'addEventListener');
191+
const fix = TestBed.createComponent(DefaultGridComponent);
192+
fix.detectChanges();
193+
194+
const grid = fix.componentInstance.instance;
195+
const cellElem = fix.debugElement.query(By.css(CELL_CSS_CLASS));
196+
const firstCell = grid.getCellByColumn(0, 'index');
197+
198+
// should attach 'doubletap'
199+
expect(addListenerSpy.calls.count()).toBeGreaterThan(1);
200+
expect(addListenerSpy).toHaveBeenCalledWith(firstCell.nativeElement, 'doubletap', firstCell.onDoubleClick, { cssProps: { } });
201+
202+
spyOn(grid.onDoubleClick, 'emit').and.callThrough();
203+
204+
const event = {
205+
type: 'doubletap',
206+
preventDefault: jasmine.createSpy('preventDefault')
207+
};
208+
firstCell.onDoubleClick(event as any);
209+
const args: IGridCellEventArgs = {
210+
cell: firstCell,
211+
event
212+
} as any;
213+
214+
fix.detectChanges();
215+
expect(event.preventDefault).toHaveBeenCalled();
182216
expect(grid.onDoubleClick.emit).toHaveBeenCalledWith(args);
183217
expect(firstCell).toBe(fix.componentInstance.clickedCell);
184218
});

projects/igniteui-angular/src/lib/grids/hierarchical-grid/hierarchical-cell.component.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,14 @@ import { ChangeDetectorRef, ElementRef, ChangeDetectionStrategy, Component,
55
import { IgxHierarchicalGridComponent } from './hierarchical-grid.component';
66
import { IgxHierarchicalSelectionAPIService } from './selection';
77
import { IgxGridSelectionService, IgxGridCRUDService } from '../../core/grid-selection';
8+
import { HammerGesturesManager } from '../../core/touch';
89

910
@Component({
1011
changeDetection: ChangeDetectionStrategy.OnPush,
1112
preserveWhitespaces: false,
1213
selector: 'igx-hierarchical-grid-cell',
13-
templateUrl: './../cell.component.html'
14+
templateUrl: './../cell.component.html',
15+
providers: [HammerGesturesManager]
1416
})
1517
export class IgxHierarchicalGridCellComponent extends IgxGridCellComponent implements OnInit {
1618

@@ -25,8 +27,9 @@ export class IgxHierarchicalGridCellComponent extends IgxGridCellComponent imple
2527
public cdr: ChangeDetectorRef,
2628
private helement: ElementRef,
2729
protected zone: NgZone,
30+
touchManager: HammerGesturesManager
2831
) {
29-
super(selectionService, crudService, gridAPI, selection, cdr, helement, zone);
32+
super(selectionService, crudService, gridAPI, selection, cdr, helement, zone, touchManager);
3033
this.hSelection = <IgxHierarchicalSelectionAPIService>selection;
3134
}
3235

projects/igniteui-angular/src/lib/grids/tree-grid/tree-cell.component.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,13 @@ import { getNodeSizeViaRange } from '../../core/utils';
77
import { DOCUMENT } from '@angular/common';
88
import { IgxGridBaseComponent, IGridDataBindable } from '../grid';
99
import { IgxGridSelectionService, IgxGridCRUDService } from '../../core/grid-selection';
10+
import { HammerGesturesManager } from '../../core/touch';
1011

1112
@Component({
1213
changeDetection: ChangeDetectionStrategy.OnPush,
1314
selector: 'igx-tree-grid-cell',
14-
templateUrl: 'tree-cell.component.html'
15+
templateUrl: 'tree-cell.component.html',
16+
providers: [HammerGesturesManager]
1517
})
1618
export class IgxTreeGridCellComponent extends IgxGridCellComponent implements OnInit {
1719
private treeGridAPI: IgxTreeGridAPIService;
@@ -24,8 +26,9 @@ export class IgxTreeGridCellComponent extends IgxGridCellComponent implements On
2426
cdr: ChangeDetectorRef,
2527
element: ElementRef,
2628
protected zone: NgZone,
29+
touchManager: HammerGesturesManager,
2730
@Inject(DOCUMENT) public document) {
28-
super(selectionService, crudService, gridAPI, selection, cdr, element, zone);
31+
super(selectionService, crudService, gridAPI, selection, cdr, element, zone, touchManager);
2932
this.treeGridAPI = <IgxTreeGridAPIService>gridAPI;
3033
}
3134

0 commit comments

Comments
 (0)