Skip to content

Commit d0b940d

Browse files
authored
Merge branch 'master' into simeonoff/fix-8257
2 parents 92a9fbf + e820727 commit d0b940d

File tree

10 files changed

+100
-30
lines changed

10 files changed

+100
-30
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,7 @@ export const NAVIGATION_KEYS = new Set([
324324
]);
325325
export const ROW_EXPAND_KEYS = new Set('right down arrowright arrowdown'.split(' '));
326326
export const ROW_COLLAPSE_KEYS = new Set('left up arrowleft arrowup'.split(' '));
327-
export const SUPPORTED_KEYS = new Set([...Array.from(NAVIGATION_KEYS), 'enter', 'f2', 'escape', 'esc', 'pagedown', 'pageup']);
327+
export const SUPPORTED_KEYS = new Set([...Array.from(NAVIGATION_KEYS), 'enter', 'f2', 'escape', 'esc', 'pagedown', 'pageup', '+']);
328328
export const HEADER_KEYS = new Set([...Array.from(NAVIGATION_KEYS), 'escape', 'esc' , 'l']);
329329

330330
/**

projects/igniteui-angular/src/lib/grids/grid-base.directive.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4378,7 +4378,7 @@ export abstract class IgxGridBaseDirective extends DisplayDensityBase implements
43784378
public refreshGridState(args?) {
43794379
this.endEdit(true);
43804380
this.selectionService.clearHeaderCBState();
4381-
this.summaryService.clearSummaryCache(args);
4381+
this.summaryService.clearSummaryCache();
43824382
}
43834383

43844384
// TODO: We have return values here. Move them to event args ??

projects/igniteui-angular/src/lib/grids/grid-navigation.service.ts

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ export class IgxGridNavigationService {
5050
if (!this.activeNode || !(SUPPORTED_KEYS.has(key) || (key === 'tab' && this.grid.crudService.cell))) { return; }
5151
const shift = event.shiftKey;
5252
const ctrl = event.ctrlKey;
53+
const alt = event.altKey;
5354
if (NAVIGATION_KEYS.has(key) && this.pendingNavigation) { event.preventDefault(); return; }
5455

5556
const type = this.isDataRow(this.activeNode.row) ? 'dataCell' :
@@ -262,9 +263,20 @@ export class IgxGridNavigationService {
262263
protected handleAlt(key: string, event: KeyboardEvent) {
263264
event.preventDefault();
264265
const row = this.grid.getRowByIndex(this.activeNode.row) as any;
265-
if (!this.isToggleKey(key) || !row) { return; }
266266

267-
if (!row.expanded && ROW_EXPAND_KEYS.has(key)) {
267+
if (!(this.isToggleKey(key) || this.isAddKey(key)) || !row) { return; }
268+
if (this.isAddKey(key)) {
269+
if (!this.grid.rowEditable) {
270+
console.warn('The grid must be in row edit mode to perform row adding!');
271+
return;
272+
}
273+
274+
if (event.shiftKey && row.treeRow !== undefined) {
275+
row.beginAddChild();
276+
} else if (!event.shiftKey) {
277+
row.beginAddRow();
278+
}
279+
} else if (!row.expanded && ROW_EXPAND_KEYS.has(key)) {
268280
row.rowID === undefined ? row.toggle() :
269281
this.grid.gridAPI.set_row_expansion_state(row.rowID, true, event);
270282
} else if (row.expanded && ROW_COLLAPSE_KEYS.has(key)) {
@@ -607,4 +619,8 @@ export class IgxGridNavigationService {
607619
private isToggleKey(key: string): boolean {
608620
return ROW_COLLAPSE_KEYS.has(key) || ROW_EXPAND_KEYS.has(key);
609621
}
622+
623+
private isAddKey(key: string): boolean {
624+
return key === '+';
625+
}
610626
}

projects/igniteui-angular/src/lib/grids/grid.rowEdit.directive.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,27 @@
11
import { Directive, ElementRef, HostListener } from '@angular/core';
22
import { GridBaseAPIService } from './api.service';
3-
import { GridType } from './common/grid.interface';
43

5-
/** @hidden */
4+
/** @hidden @internal */
65
@Directive({
76
selector: '[igxRowEdit]'
87
})
98
export class IgxRowEditTemplateDirective { }
109

11-
/** @hidden */
10+
/** @hidden @internal */
1211
@Directive({
1312
selector: '[igxRowEditText]'
1413
})
1514
export class IgxRowEditTextDirective { }
1615

17-
/** @hidden */
16+
/** @hidden @internal */
1817
@Directive({
1918
selector: '[igxRowEditActions]'
2019
})
2120
export class IgxRowEditActionsDirective { }
2221

2322

2423
// TODO: Refactor circular ref, deps and logic
25-
/** @hidden */
24+
/** @hidden @internal */
2625
@Directive({
2726
selector: `[igxRowEditTabStop]`
2827
})

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

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { NoopAnimationsModule } from '@angular/platform-browser/animations';
33
import { async, TestBed, fakeAsync } from '@angular/core/testing';
44
import { configureTestSuite } from '../../test-utils/configure-suite';
55
import { DebugElement } from '@angular/core';
6-
import { GridFunctions } from '../../test-utils/grid-functions.spec';
6+
import { GridFunctions, GridSummaryFunctions } from '../../test-utils/grid-functions.spec';
77
import {
88
IgxAddRowComponent
99
} from '../../test-utils/grid-samples.spec';
@@ -14,6 +14,7 @@ import { IgxActionStripModule } from '../../action-strip/action-strip.module';
1414
import { UIInteractions, wait } from '../../test-utils/ui-interactions.spec';
1515

1616
describe('IgxGrid - Row Adding #grid', () => {
17+
const SUMMARY_ROW = 'igx-grid-summary-row';
1718
let fixture;
1819
let grid: IgxGridComponent;
1920
let gridContent: DebugElement;
@@ -98,7 +99,28 @@ describe('IgxGrid - Row Adding #grid', () => {
9899
// No much space between the row and the banner
99100
expect(addRowTop - bannerBottom).toBeLessThan(2);
100101
});
102+
it('Should be able to enter add row mode on Alt + plus key.', () => {
103+
GridFunctions.focusFirstCell(fixture);
104+
fixture.detectChanges();
105+
106+
UIInteractions.triggerEventHandlerKeyDown('+', gridContent, true, false, false);
107+
fixture.detectChanges();
101108

109+
const addRow = grid.getRowByIndex(1);
110+
expect(addRow.addRow).toBeTrue();
111+
112+
});
113+
it('Should not be able to enter add row mode on Alt + Shift + plus key.', () => {
114+
GridFunctions.focusFirstCell(fixture);
115+
fixture.detectChanges();
116+
117+
UIInteractions.triggerEventHandlerKeyDown('+', gridContent, true, true, false);
118+
fixture.detectChanges();
119+
120+
const banner = GridFunctions.getRowEditingOverlay(fixture);
121+
expect(banner).toBeNull();
122+
expect(grid.getRowByIndex(1).addRow).toBeFalse();
123+
});
102124
it('Should not be able to enter add row mode when rowEditing is disabled', () => {
103125
grid.rowEditable = false;
104126
fixture.detectChanges();
@@ -175,5 +197,21 @@ describe('IgxGrid - Row Adding #grid', () => {
175197
expect(rowOffsets.top >= gridOffsets.top && rowOffsets.bottom <= gridOffsets.bottom).toBeTruthy();
176198
});
177199

200+
it('should update summaries after row is added via the UI.', () => {
201+
grid.getColumnByName('ID').hasSummary = true;
202+
fixture.detectChanges();
203+
let summaryRow = fixture.debugElement.query(By.css(SUMMARY_ROW));
204+
GridSummaryFunctions.verifyColumnSummaries(summaryRow, 0, ['Count'], ['27']);
205+
206+
grid.rowList.first.beginAddRow();
207+
fixture.detectChanges();
208+
209+
grid.endEdit(true);
210+
fixture.detectChanges();
211+
212+
summaryRow = fixture.debugElement.query(By.css(SUMMARY_ROW));
213+
GridSummaryFunctions.verifyColumnSummaries(summaryRow, 0, ['Count'], ['28']);
214+
});
215+
178216
});
179217
});

projects/igniteui-angular/src/lib/time-picker/time-picker.component.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
</ng-template>
44

55
<ng-template #dropdownInputTemplate>
6-
<igx-input-group #group (mousedown)="mouseDown($event)">
6+
<igx-input-group #group (mousedown)="mouseDown($event)" [suppressInputAutofocus]="true">
77
<label igxLabel *ngIf="!labelDirective">Time</label>
88
<ng-container ngProjectAs="[igxLabel]" *ngTemplateOutlet="labelTemplate"></ng-container>
99
<igx-prefix (click)="openDialog(group.element.nativeElement)">

projects/igniteui-angular/src/lib/time-picker/time-picker.component.spec.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1873,7 +1873,6 @@ describe('IgxTimePicker', () => {
18731873
fixture.componentInstance.format = 'hh tt';
18741874
fixture.componentInstance.customDate = new Date(2018, 10, 27, 17, 45, 0, 0);
18751875
fixture.detectChanges();
1876-
18771876
const clearTime = dom.queryAll(By.css('.igx-icon'))[1];
18781877

18791878
UIInteractions.simulateClickAndSelectEvent(clearTime);
@@ -1893,6 +1892,21 @@ describe('IgxTimePicker', () => {
18931892
expect(input.nativeElement.value).toBe('-- AM');
18941893
}));
18951894

1895+
it('should allow editing of input after clear', fakeAsync(() => {
1896+
fixture.componentInstance.format = 'hh tt';
1897+
fixture.componentInstance.customDate = new Date(2018, 10, 27, 17, 45, 0, 0);
1898+
fixture.detectChanges();
1899+
spyOn(fixture.componentInstance.timePicker, 'onInput');
1900+
1901+
const clearTime = dom.queryAll(By.css('.igx-icon'))[1];
1902+
UIInteractions.simulateClickAndSelectEvent(clearTime);
1903+
fixture.detectChanges();
1904+
const _input = fixture.debugElement.query(By.css('input'));
1905+
UIInteractions.simulateTyping('12 AM', _input);
1906+
expect(fixture.componentInstance.timePicker.onInput).not.toThrow();
1907+
expect(_input.nativeElement.value).toEqual('12 AM');
1908+
}));
1909+
18961910
it('Should navigate dropdown lists correctly when format contains only hours.', fakeAsync(() => {
18971911
fixture.componentInstance.format = 'hh tt';
18981912
fixture.componentInstance.customDate = new Date(2018, 10, 27, 17, 45, 0);

projects/igniteui-angular/src/lib/time-picker/time-picker.component.ts

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ import { ITimePickerResourceStrings } from '../core/i18n/time-picker-resources';
5050
import { CurrentResourceStrings } from '../core/i18n/resources';
5151
import { KEYS, CancelableBrowserEventArgs, IBaseEventArgs } from '../core/utils';
5252
import { InteractionMode } from '../core/enums';
53-
import { IgxTextSelectionModule} from '../directives/text-selection/text-selection.directive';
53+
import { IgxTextSelectionModule } from '../directives/text-selection/text-selection.directive';
5454
import { IgxLabelDirective } from '../directives/label/label.directive';
5555

5656

@@ -1951,9 +1951,12 @@ export class IgxTimePickerComponent implements
19511951
this.isNotEmpty = false;
19521952

19531953
const oldVal = new Date(this.value);
1954-
1955-
this.displayValue = '';
1956-
this.value.setHours(0, 0);
1954+
this.displayValue = this.parseMask(false);
1955+
requestAnimationFrame(() => {
1956+
this._setCursorPosition(0);
1957+
});
1958+
// TODO: refactoring - this.value should be null #6585
1959+
this.value?.setHours(0, 0, 0);
19571960

19581961
if (oldVal.getTime() !== this.value.getTime()) {
19591962
const args: IgxTimePickerValueChangedEventArgs = {
@@ -1971,35 +1974,35 @@ export class IgxTimePickerComponent implements
19711974
* @hidden
19721975
*/
19731976
public onInput(event): void {
1974-
const val = event.target.value;
1977+
const inputMask: string = event.target.value;
19751978
const oldVal = new Date(this.value);
19761979

1977-
this.isNotEmpty = val !== this.parseMask(false);
1980+
this.isNotEmpty = inputMask !== this.parseMask(false);
19781981

19791982
// handle cases where all empty positions (promts) are filled and we want to update
19801983
// timepicker own value property if it is a valid Date
1981-
if (val.indexOf(this.promptChar) === -1) {
1982-
if (this._isEntryValid(val)) {
1983-
const newVal = this.convertMinMaxValue(val);
1984+
if (inputMask.indexOf(this.promptChar) === -1) {
1985+
if (this._isEntryValid(inputMask)) {
1986+
const newVal = this.convertMinMaxValue(inputMask);
19841987
if (oldVal.getTime() !== newVal.getTime()) {
19851988
this.value = newVal;
19861989
}
19871990
} else {
19881991
const args: IgxTimePickerValidationFailedEventArgs = {
19891992
timePicker: this,
1990-
currentValue: val,
1993+
currentValue: new Date(inputMask),
19911994
setThroughUI: false
19921995
};
19931996
this.onValidationFailed.emit(args);
19941997
}
19951998
// handle cases where the user deletes the display value (when pressing backspace or delete)
1996-
} else if (!this.value || !val || val === this.parseMask(false)) {
1999+
} else if (!this.value || inputMask.length === 0 || !this.isNotEmpty) {
19972000
this.isNotEmpty = false;
1998-
1999-
this.value.setHours(0, 0);
2000-
this.displayValue = val;
2001-
2002-
if (oldVal.getTime() !== this.value.getTime()) {
2001+
// TODO: refactoring - this.value should be null #6585
2002+
this.value?.setHours(0, 0, 0);
2003+
this.displayValue = inputMask;
2004+
if (oldVal.getTime() !== this.value?.getTime()) {
2005+
// TODO: Do not emit event when the editor is empty #6482
20032006
const args: IgxTimePickerValueChangedEventArgs = {
20042007
oldValue: oldVal,
20052008
newValue: this.value
@@ -2026,7 +2029,7 @@ export class IgxTimePickerComponent implements
20262029
this.isNotEmpty = value !== '';
20272030
this.displayValue = value;
20282031

2029-
if (value && value !== this.parseMask()) {
2032+
if (value && (value !== this.parseMask() || value !== this.parseMask(false))) {
20302033
if (this._isEntryValid(value)) {
20312034
const newVal = this.convertMinMaxValue(value);
20322035
if (!this.value || this.value.getTime() !== newVal.getTime()) {

src/app/grid-add-row/grid-add-row.sample.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
[pinned]="c.pinned"
2020
[hidden]="c.hidden"
2121
[groupable]='true'
22+
[hasSummary]="true"
2223
>
2324
</igx-column>
2425

src/app/grid-add-row/grid-add-row.sample.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ export class GridAddRowSampleComponent implements OnInit {
1313

1414
data: any[];
1515
columns: any[];
16-
1716
onMouseOver(event, grid, actionStrip) {
1817
if (event.target.nodeName.toLowerCase() === 'igx-grid-cell') {
1918
const rowIndex = parseInt(event.target.attributes['data-rowindex'].value, 10);

0 commit comments

Comments
 (0)