Skip to content

Commit 91d5d0b

Browse files
authored
Merge pull request #4466 from IgniteUI/rkaraivanov/grid-cell-ie11-fixes
fix(igx-cell): Focus and IME input handlers
2 parents b3e9e12 + 76d9fbb commit 91d5d0b

File tree

3 files changed

+118
-60
lines changed

3 files changed

+118
-60
lines changed

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

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,12 @@
88
<ng-template #inlineEditor let-cell="cell">
99
<ng-container *ngIf="column.dataType === 'string'">
1010
<igx-input-group displayDensity="compact">
11-
<input igxInput [value]="editValue" (input)="editValue = $event.target.value"
12-
(compositionstart)="isInCompositionMode = true" (compositionend)="isInCompositionMode = false"
13-
[igxFocus]="focused" />
11+
<input igxInput [value]="editValue" (input)="editValue = $event.target.value" [igxFocus]="focused" />
1412
</igx-input-group>
1513
</ng-container>
1614
<ng-container *ngIf="column.dataType === 'number'">
1715
<igx-input-group displayDensity="compact">
18-
<input igxInput [value]="editValue" (input)="editValue = $event.target.value"
19-
(compositionstart)="isInCompositionMode = true" (compositionend)="isInCompositionMode = false"
20-
[igxFocus]="focused" type="number">
16+
<input igxInput [value]="editValue" (input)="editValue = $event.target.value" [igxFocus]="focused" type="number">
2117
</igx-input-group>
2218
</ng-container>
2319
<ng-container *ngIf="column.dataType === 'boolean'">
@@ -26,7 +22,7 @@
2622
</ng-container>
2723
<ng-container *ngIf="column.dataType === 'date'">
2824
<igx-date-picker [style.width.%]="100" [outlet]="grid.outletDirective" mode="dropdown" (onSelection)="editValue = $event"
29-
[locale]="grid.locale" [(ngModel)]="editValue" [igxFocus]="focused" [labelVisibility]="false">
25+
[locale]="grid.locale" [value]="editValue" [igxFocus]="focused" [labelVisibility]="false">
3026
</igx-date-picker>
3127
</ng-container>
3228
</ng-template>

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

Lines changed: 114 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,11 @@ import { IgxSelectionAPIService } from '../core/selection';
1818
import { IgxTextHighlightDirective } from '../directives/text-highlight/text-highlight.directive';
1919
import { GridBaseAPIService } from './api.service';
2020
import { IgxColumnComponent } from './column.component';
21-
import { getNodeSizeViaRange, ROW_COLLAPSE_KEYS, ROW_EXPAND_KEYS, SUPPORTED_KEYS, NAVIGATION_KEYS } from '../core/utils';
21+
import { getNodeSizeViaRange, ROW_COLLAPSE_KEYS, ROW_EXPAND_KEYS, SUPPORTED_KEYS, NAVIGATION_KEYS, isIE } from '../core/utils';
2222
import { State } from '../services/index';
2323
import { IgxGridBaseComponent, IGridEditEventArgs, IGridDataBindable } from './grid-base.component';
2424
import { IgxGridSelectionService, ISelectionNode, IgxGridCRUDService } from '../core/grid-selection';
25+
import { DeprecateProperty } from '../core/deprecateDecorators';
2526

2627
/**
2728
* Providing reference to `IgxGridCellComponent`:
@@ -259,41 +260,35 @@ export class IgxGridCellComponent implements OnInit, OnChanges, OnDestroy {
259260
}
260261

261262
/**
262-
* Gets whether the cell is in edit mode.
263+
* @deprecated
264+
* Use `cell.editMode` as a getter and
265+
* `cell.setEditMode(true | false)` to start/exit edit mode.
266+
*
267+
* Gets/sets whether the cell is in edit mode.
263268
* ```typescript
264269
* let isCellInEditMode = this.cell.inEditMode;
265270
* ```
266271
* @memberof IgxGridCellComponent
267272
*/
268-
269-
// TODO: Deprecate
270-
/**
271-
* @deprecated
272-
*/
273+
@DeprecateProperty(`'inEditMode' is deprecated\nUse 'editMode' to get the current state and 'setEditMode(boolean)' as a setter`)
273274
get inEditMode(): boolean {
274275
return this.editMode;
275276
}
276277

277278
set inEditMode(value: boolean) {
278-
if (this.row.deleted) {
279-
return;
280-
}
281-
if (this.editable && value) {
282-
this.gridAPI.submit_value();
283-
this.crudService.begin(this);
284-
} else {
285-
this.gridAPI.escape_editMode();
286-
}
287-
this.grid.cdr.markForCheck();
279+
this.setEditMode(value);
288280
}
289281

282+
/**
283+
* @hidden
284+
* @internal
285+
*/
290286
@Input()
291287
@HostBinding('class.igx-grid__td--pinned-last')
292288
lastPinned = false;
293289

294290
/**
295-
* @hidden
296-
* @internal
291+
* Returns whether the cell is in edit mode.
297292
*/
298293
@Input()
299294
@HostBinding('class.igx-grid__td--editing')
@@ -403,39 +398,12 @@ export class IgxGridCellComponent implements OnInit, OnChanges, OnDestroy {
403398

404399
return false;
405400
}
406-
@ViewChild('defaultCell', { read: TemplateRef })
407-
protected defaultCellTemplate: TemplateRef<any>;
408-
409-
@ViewChild('inlineEditor', { read: TemplateRef })
410-
protected inlineEditorTemplate: TemplateRef<any>;
411-
412-
private _highlight: IgxTextHighlightDirective;
413-
414-
@ViewChild(IgxTextHighlightDirective, { read: IgxTextHighlightDirective })
415-
protected set highlight(value: IgxTextHighlightDirective) {
416-
this._highlight = value;
417-
418-
if (this._highlight && this.grid.lastSearchInfo.searchText) {
419-
this._highlight.highlight(this.grid.lastSearchInfo.searchText,
420-
this.grid.lastSearchInfo.caseSensitive,
421-
this.grid.lastSearchInfo.exactMatch);
422-
this._highlight.activateIfNecessary();
423-
}
424-
}
425-
426-
protected get highlight() {
427-
return this._highlight;
428-
}
429-
430-
protected get selectionNode(): ISelectionNode {
431-
return { row: this.rowIndex, column: this.visibleColumnIndex };
432-
}
433401

434402
/**
435403
* Sets the current edit value while a cell is in edit mode.
436404
* Only for cell editing mode.
437405
* ```typescript
438-
* let isLastPinned = this.cell.isLastPinned;
406+
* this.cell.editValue = value;
439407
* ```
440408
* @memberof IgxGridCellComponent
441409
*/
@@ -459,15 +427,53 @@ export class IgxGridCellComponent implements OnInit, OnChanges, OnDestroy {
459427
}
460428
}
461429

430+
/**
431+
* Returns whether the cell is editable.
432+
*/
462433
get editable(): boolean {
463434
return this.column.editable;
464435
}
465436

466-
public isInCompositionMode = false;
467-
437+
/**
438+
* @hidden
439+
* @internal
440+
*/
468441
@HostBinding('class.igx-grid__td--active')
469442
public focused = false;
470443

444+
@ViewChild('defaultCell', { read: TemplateRef })
445+
protected defaultCellTemplate: TemplateRef<any>;
446+
447+
@ViewChild('inlineEditor', { read: TemplateRef })
448+
protected inlineEditorTemplate: TemplateRef<any>;
449+
450+
@ViewChild(IgxTextHighlightDirective, { read: IgxTextHighlightDirective })
451+
protected set highlight(value: IgxTextHighlightDirective) {
452+
this._highlight = value;
453+
454+
if (this._highlight && this.grid.lastSearchInfo.searchText) {
455+
this._highlight.highlight(this.grid.lastSearchInfo.searchText,
456+
this.grid.lastSearchInfo.caseSensitive,
457+
this.grid.lastSearchInfo.exactMatch);
458+
this._highlight.activateIfNecessary();
459+
}
460+
}
461+
462+
protected get highlight() {
463+
return this._highlight;
464+
}
465+
466+
protected get selectionNode(): ISelectionNode {
467+
return { row: this.rowIndex, column: this.visibleColumnIndex };
468+
}
469+
470+
protected isInCompositionMode = false;
471+
protected compositionStartHandler;
472+
protected compositionEndHandler;
473+
protected focusHandlerIE;
474+
protected focusOut;
475+
private _highlight: IgxTextHighlightDirective;
476+
471477

472478
constructor(
473479
protected selectionService: IgxGridSelectionService,
@@ -479,22 +485,53 @@ export class IgxGridCellComponent implements OnInit, OnChanges, OnDestroy {
479485
protected zone: NgZone) { }
480486

481487

488+
/**
489+
* @hidden
490+
* @internal
491+
*/
482492
ngOnInit() {
483493
this.zone.runOutsideAngular(() => {
484494
this.nativeElement.addEventListener('pointerdown', this.pointerdown);
485495
this.nativeElement.addEventListener('pointerenter', this.pointerenter);
486496
this.nativeElement.addEventListener('pointerup', this.pointerup);
497+
498+
// IE 11 workarounds
499+
if (isIE()) {
500+
// Hitting Enter with IME submits and exits from edit mode instead of first closing the IME dialog
501+
this.compositionStartHandler = this.nativeElement
502+
.addEventListener('compositionstart', () => this.isInCompositionMode = true);
503+
this.compositionEndHandler = this.nativeElement.addEventListener('compositionend', () => this.isInCompositionMode = false);
504+
505+
// https://stackoverflow.com/q/51404782
506+
this.focusHandlerIE = this.nativeElement.addEventListener('focusin', (e: FocusEvent) => this.onFocus(e));
507+
this.focusOut = this.nativeElement.addEventListener('focusout', () => this.onBlur());
508+
}
487509
});
488510
}
489511

512+
/**
513+
* @hidden
514+
* @internal
515+
*/
490516
ngOnDestroy() {
491517
this.zone.runOutsideAngular(() => {
492518
this.nativeElement.removeEventListener('pointerdown', this.pointerdown);
493519
this.nativeElement.removeEventListener('pointerenter', this.pointerenter);
494520
this.nativeElement.removeEventListener('pointerup', this.pointerup);
521+
522+
if (isIE()) {
523+
this.nativeElement.removeEventListener('compositionstart', this.compositionStartHandler);
524+
this.nativeElement.removeEventListener('compositionend', this.compositionEndHandler);
525+
this.nativeElement.removeEventListener('focusin', this.focusHandlerIE);
526+
this.nativeElement.removeEventListener('focusout', this.focusOut);
527+
}
495528
});
496529
}
497530

531+
/**
532+
* @hidden
533+
* @internal
534+
*/
498535
_updateCRUDStatus() {
499536
if (this.editable && this.crudService.inEditMode && !this.row.deleted) {
500537
this.gridAPI.update_cell(this.crudService.cell, this.crudService.cell.editValue);
@@ -533,7 +570,8 @@ export class IgxGridCellComponent implements OnInit, OnChanges, OnDestroy {
533570
}
534571

535572
/**
536-
*@hidden
573+
* @hidden
574+
* @internal
537575
*/
538576
public ngOnChanges(changes: SimpleChanges): void {
539577
if (changes.value && !changes.value.firstChange) {
@@ -545,6 +583,26 @@ export class IgxGridCellComponent implements OnInit, OnChanges, OnDestroy {
545583
}
546584
}
547585

586+
/**
587+
* Starts/ends edit mode for the cell.
588+
*
589+
* ```typescript
590+
* cell.setEditMode(true);
591+
* ```
592+
*/
593+
setEditMode(value: boolean): void {
594+
if (this.row.deleted) {
595+
return;
596+
}
597+
if (this.editable && value) {
598+
this.gridAPI.submit_value();
599+
this.crudService.begin(this);
600+
} else {
601+
this.gridAPI.escape_editMode();
602+
}
603+
this.grid.cdr.markForCheck();
604+
}
605+
548606
/**
549607
* Sets new value to the cell.
550608
* ```typescript
@@ -663,7 +721,7 @@ export class IgxGridCellComponent implements OnInit, OnChanges, OnDestroy {
663721
this.row.focused = false;
664722
}
665723

666-
protected handleAlt(key: string) {
724+
protected handleAlt(key: string, event: KeyboardEvent) {
667725
if (this.row.nativeElement.tagName.toLowerCase() === 'igx-tree-grid-row' && this.isToggleKey(key)) {
668726
const collapse = (this.row as any).expanded && ROW_COLLAPSE_KEYS.has(key);
669727
const expand = !(this.row as any).expanded && ROW_EXPAND_KEYS.has(key);
@@ -719,7 +777,7 @@ export class IgxGridCellComponent implements OnInit, OnChanges, OnDestroy {
719777
}
720778

721779
if (event.altKey) {
722-
this.handleAlt(key);
780+
this.handleAlt(key, event);
723781
return;
724782
}
725783

@@ -839,6 +897,10 @@ export class IgxGridCellComponent implements OnInit, OnChanges, OnDestroy {
839897
* @internal
840898
*/
841899
public onKeydownExitEditMode() {
900+
if (this.isInCompositionMode) {
901+
return;
902+
}
903+
842904
if (this.editMode) {
843905
const v = this.crudService.cell;
844906
const args = {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ import { IgxGridSelectionService, IgxGridCRUDService } from '../../core/grid-sel
3636

3737
import { IgxOverlayService } from '../../services/index';
3838
import { takeUntil } from 'rxjs/operators';
39-
import { IgxColumnComponent } from '../grid';
39+
import { IgxColumnComponent } from '../column.component';
4040
import { IgxRowIslandAPIService } from './row-island-api.service';
4141
export interface IGridCreatedEventArgs {
4242
owner: IgxRowIslandComponent;

0 commit comments

Comments
 (0)