Skip to content

Commit 2e62f6e

Browse files
authored
Merge pull request #5461 from IgniteUI/dpetev/ios-grid-edit-7-2
fix(grids): handle double tap to allow editing on iOS #2538
2 parents 0213744 + 2051d12 commit 2e62f6e

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
@@ -19,11 +19,11 @@ export class HammerGesturesManager {
1919
inputClass: Hammer.TouchInput,
2020
recognizers: [
2121
[ Hammer.Pan, { threshold: 0 } ],
22-
[ Hammer.Pinch, { enable: true } ],
23-
[ Hammer.Rotate, { enable: true } ],
2422
[ Hammer.Swipe, {
2523
direction: Hammer.DIRECTION_HORIZONTAL
26-
}]
24+
}],
25+
[Hammer.Tap],
26+
[Hammer.Tap, { event: 'doubletap', taps: 2 }, ['tap']]
2727
]
2828
};
2929

@@ -43,14 +43,14 @@ export class HammerGesturesManager {
4343
public addEventListener(element: HTMLElement,
4444
eventName: string,
4545
eventHandler: (eventObj) => void,
46-
options: object = null): () => void {
46+
options: HammerOptions = null): () => void {
4747

4848
// Creating the manager bind events, must be done outside of angular
4949
return this._zone.runOutsideAngular(() => {
5050
let mc: HammerManager = this.getManagerForElement(element);
5151
if (mc === null) {
5252
// new Hammer is a shortcut for Manager with defaults
53-
mc = new Hammer(element, this.hammerOptions);
53+
mc = new Hammer(element, Object.assign(this.hammerOptions, options));
5454
this.addManagerForElement(element, mc);
5555
}
5656
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

@@ -482,7 +484,8 @@ export class IgxGridCellComponent implements OnInit, OnChanges, OnDestroy {
482484
public selection: IgxSelectionAPIService,
483485
public cdr: ChangeDetectorRef,
484486
private element: ElementRef,
485-
protected zone: NgZone) { }
487+
protected zone: NgZone,
488+
private touchManager: HammerGesturesManager) { }
486489

487490

488491
/**
@@ -510,6 +513,9 @@ export class IgxGridCellComponent implements OnInit, OnChanges, OnDestroy {
510513
this.nativeElement.addEventListener('focusout', this.focusOut);
511514
}
512515
});
516+
this.touchManager.addEventListener(this.nativeElement, 'doubletap', this.onDoubleClick, {
517+
cssProps: { } /* don't disable user-select, etc */
518+
} as HammerOptions);
513519
}
514520

515521
/**
@@ -529,6 +535,7 @@ export class IgxGridCellComponent implements OnInit, OnChanges, OnDestroy {
529535
this.nativeElement.removeEventListener('focusout', this.focusOut);
530536
}
531537
});
538+
this.touchManager.destroy();
532539
}
533540

534541
/**
@@ -674,7 +681,11 @@ export class IgxGridCellComponent implements OnInit, OnChanges, OnDestroy {
674681
* @internal
675682
*/
676683
@HostListener('dblclick', ['$event'])
677-
public onDoubleClick(event: MouseEvent) {
684+
public onDoubleClick = (event: MouseEvent | HammerInput) => {
685+
if (event.type === 'doubletap') {
686+
// prevent double-tap to zoom on iOS
687+
(event as HammerInput).preventDefault();
688+
}
678689
if (this.editable && !this.editMode && !this.row.deleted) {
679690
this.crudService.begin(this);
680691
}

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, IgxNumberFilteringOperand } 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)