Skip to content

Commit 7eaf60e

Browse files
Merge branch '18.2.x' into aahmedov/fix-touched-invalid-color-follow-up-18.2.x
2 parents fe66d30 + eca1c18 commit 7eaf60e

23 files changed

+342
-289
lines changed

.github/workflows/codeql-analysis.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,10 @@ name: "CodeQL"
1313

1414
on:
1515
push:
16-
branches: [ master, 18.1.x, 17.2.x, 16.1.x, 15.1.x ]
16+
branches: [ master, 18.2.x, 17.2.x, 16.1.x, 15.1.x ]
1717
pull_request:
1818
# The branches below must be a subset of the branches above
19-
branches: [ master, 18.1.x, 17.2.x, 16.1.x, 15.1.x ]
19+
branches: [ master, 18.2.x, 17.2.x, 16.1.x, 15.1.x ]
2020
schedule:
2121
- cron: '33 4 * * 4'
2222

package-lock.json

Lines changed: 43 additions & 141 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@
136136
"postcss": "^8.4.31",
137137
"postcss-scss": "^4.0.6",
138138
"prettier": "^3.3.2",
139-
"puppeteer": "^23.3.0",
139+
"puppeteer": "^23.6.1",
140140
"sass-embedded": "^1.77.5",
141141
"sass-true": "^6.0.1",
142142
"sassdoc": "^2.7.4",

projects/igniteui-angular/src/lib/combo/combo.common.ts

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -179,17 +179,11 @@ export abstract class IgxComboBaseDirective implements IgxComboBase, AfterViewCh
179179
return;
180180
}
181181
const selection = this.selectionService.get(this._id);
182+
this.selectionService.clear(this._id);
182183
this._id = value;
183184
if (selection) {
184185
this.selectionService.set(this._id, selection);
185186
}
186-
if (this.dropdown?.open) {
187-
this.dropdown.close();
188-
}
189-
if (this.inputGroup?.isFocused) {
190-
this.inputGroup.element.nativeElement.blur();
191-
this.inputGroup.isFocused = false;
192-
}
193187
}
194188

195189
/**

projects/igniteui-angular/src/lib/combo/combo.component.spec.ts

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import {
66
} from '@angular/forms';
77
import { By } from '@angular/platform-browser';
88
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
9-
import { BehaviorSubject, Observable } from 'rxjs';
9+
import { BehaviorSubject, Observable, firstValueFrom } from 'rxjs';
1010
import { take } from 'rxjs/operators';
1111
import { IgxSelectionAPIService } from '../core/selection';
1212
import { IBaseCancelableBrowserEventArgs } from '../core/utils';
@@ -1532,7 +1532,7 @@ describe('igxCombo', () => {
15321532

15331533
productIndex = 42;
15341534
combo.virtualScrollContainer.scrollTo(productIndex);
1535-
await wait();
1535+
await firstValueFrom(combo.virtualScrollContainer.chunkLoad);
15361536
fixture.detectChanges();
15371537
verifyComboData();
15381538
// index is at bottom
@@ -1541,21 +1541,21 @@ describe('igxCombo', () => {
15411541

15421542
productIndex = 485;
15431543
combo.virtualScrollContainer.scrollTo(productIndex);
1544-
await wait(30);
1544+
await firstValueFrom(combo.virtualScrollContainer.chunkLoad);
15451545
fixture.detectChanges();
15461546
verifyComboData();
15471547
expect(combo.virtualizationState.startIndex + combo.virtualizationState.chunkSize - 1)
15481548
.toEqual(productIndex);
15491549

15501550
productIndex = 873;
15511551
combo.virtualScrollContainer.scrollTo(productIndex);
1552-
await wait();
1552+
await firstValueFrom(combo.virtualScrollContainer.chunkLoad);
15531553
fixture.detectChanges();
15541554
verifyComboData();
15551555

15561556
productIndex = 649;
15571557
combo.virtualScrollContainer.scrollTo(productIndex);
1558-
await wait();
1558+
await firstValueFrom(combo.virtualScrollContainer.chunkLoad);
15591559
fixture.detectChanges();
15601560
verifyComboData();
15611561
});
@@ -1578,7 +1578,7 @@ describe('igxCombo', () => {
15781578

15791579
// Scroll selected items out of view
15801580
combo.virtualScrollContainer.scrollTo(40);
1581-
await wait();
1581+
await firstValueFrom(combo.virtualScrollContainer.chunkLoad);
15821582
fixture.detectChanges();
15831583
combo.handleClearItems(spyObj);
15841584
expect(combo.selection).toEqual([]);
@@ -1604,7 +1604,7 @@ describe('igxCombo', () => {
16041604

16051605
// scroll to second selected item
16061606
combo.virtualScrollContainer.scrollTo(19);
1607-
await wait(30);
1607+
await firstValueFrom(combo.virtualScrollContainer.chunkLoad);
16081608
fixture.detectChanges();
16091609

16101610
const secondItem = combo.data[combo.data.length - 1];
@@ -1633,7 +1633,7 @@ describe('igxCombo', () => {
16331633

16341634
// Scroll selected items out of view
16351635
combo.virtualScrollContainer.scrollTo(40);
1636-
await wait();
1636+
await firstValueFrom(combo.virtualScrollContainer.chunkLoad);
16371637
fixture.detectChanges();
16381638
combo.select([combo.data[0][valueKey], combo.data[1][valueKey]]);
16391639
Object.assign(expectedResults, {
@@ -1969,14 +1969,14 @@ describe('igxCombo', () => {
19691969
expect(scrollbar.scrollTop).toEqual(0);
19701970
// Scroll to bottom;
19711971
UIInteractions.triggerEventHandlerKeyDown('End', dropdownContent);
1972-
await wait(30);
1972+
await firstValueFrom(combo.virtualScrollContainer.chunkLoad);
19731973
fixture.detectChanges();
19741974
// Content was scrolled to bottom
19751975
expect(scrollbar.scrollHeight - scrollbar.scrollTop).toEqual(scrollbar.clientHeight);
19761976

19771977
// Scroll to top
19781978
UIInteractions.triggerEventHandlerKeyDown('Home', dropdownContent);
1979-
await wait(30);
1979+
await firstValueFrom(combo.virtualScrollContainer.chunkLoad);
19801980
fixture.detectChanges();
19811981
const dropdownContainer: HTMLElement = fixture.debugElement.query(By.css(`.${CSS_CLASS_CONTAINER}`)).nativeElement;
19821982
firstVisibleItem = dropdownContainer.querySelector(`.${CSS_CLASS_DROPDOWNLISTITEM}` + ':first-child');
@@ -2013,14 +2013,14 @@ describe('igxCombo', () => {
20132013
expect(scrollbar.scrollTop).toEqual(0);
20142014
// Scroll to bottom;
20152015
UIInteractions.triggerEventHandlerKeyDown('End', dropdownContent);
2016-
await wait();
2016+
await firstValueFrom(combo.virtualScrollContainer.chunkLoad);
20172017
fixture.detectChanges();
20182018
// Content was scrolled to bottom
20192019
expect(scrollbar.scrollHeight - scrollbar.scrollTop).toEqual(scrollbar.clientHeight);
20202020

20212021
// Scroll to top
20222022
UIInteractions.triggerEventHandlerKeyDown('Home', dropdownContent);
2023-
await wait(30);
2023+
await firstValueFrom(combo.virtualScrollContainer.chunkLoad);
20242024
fixture.detectChanges();
20252025
const dropdownContainer: HTMLElement = fixture.debugElement.query(By.css(`.${CSS_CLASS_CONTAINER}`)).nativeElement;
20262026
firstVisibleItem = dropdownContainer.querySelector(`.${CSS_CLASS_DROPDOWNLISTITEM}` + ':first-child');
@@ -2066,7 +2066,7 @@ describe('igxCombo', () => {
20662066
spyOn(combo.dropdown, 'onToggleClosing').and.callThrough();
20672067
spyOn(combo.dropdown, 'onToggleClosed').and.callThrough();
20682068
combo.toggle();
2069-
await wait(30);
2069+
await wait();
20702070
fixture.detectChanges();
20712071
expect(combo.collapsed).toEqual(false);
20722072
expect(combo.dropdown.onToggleOpening).toHaveBeenCalledTimes(1);
@@ -2075,17 +2075,17 @@ describe('igxCombo', () => {
20752075
expect(virtDir.getScroll().scrollTop).toEqual(0);
20762076
expect(vContainerScrollHeight).toBeGreaterThan(combo.itemHeight);
20772077
virtDir.getScroll().scrollTop = Math.floor(vContainerScrollHeight / 2);
2078-
await wait(30);
2078+
await firstValueFrom(combo.virtualScrollContainer.chunkLoad);
20792079
fixture.detectChanges();
20802080
expect(virtDir.getScroll().scrollTop).toBeGreaterThan(0);
20812081
UIInteractions.simulateClickEvent(document.documentElement);
2082-
await wait(10);
2082+
await wait();
20832083
fixture.detectChanges();
20842084
expect(combo.collapsed).toEqual(true);
20852085
expect(combo.dropdown.onToggleClosing).toHaveBeenCalledTimes(1);
20862086
expect(combo.dropdown.onToggleClosed).toHaveBeenCalledTimes(1);
20872087
combo.toggle();
2088-
await wait(30);
2088+
await wait();
20892089
fixture.detectChanges();
20902090
expect(combo.collapsed).toEqual(false);
20912091
expect(combo.dropdown.onToggleOpening).toHaveBeenCalledTimes(2);
@@ -2116,7 +2116,7 @@ describe('igxCombo', () => {
21162116
expect(scrollbar.scrollTop).toEqual(0);
21172117

21182118
combo.virtualScrollContainer.scrollTo(16);
2119-
await wait(30);
2119+
await firstValueFrom(combo.virtualScrollContainer.chunkLoad);
21202120
fixture.detectChanges();
21212121
let selectedItem = fixture.debugElement.queryAll(By.css(`.${CSS_CLASS_DROPDOWNLISTITEM}`))[1];
21222122
selectedItem.triggerEventHandler('click', UIInteractions.getMouseEvent('click'));
@@ -2126,13 +2126,13 @@ describe('igxCombo', () => {
21262126

21272127
const dropdownContent = fixture.debugElement.query(By.css(`.${CSS_CLASS_CONTENT}`));
21282128
UIInteractions.triggerEventHandlerKeyDown('End', dropdownContent);
2129-
await wait(30);
2129+
await firstValueFrom(combo.virtualScrollContainer.chunkLoad);
21302130
fixture.detectChanges();
21312131
// Content was scrolled to bottom
21322132
expect(scrollbar.scrollHeight - scrollbar.scrollTop).toEqual(scrollbar.clientHeight);
21332133

21342134
combo.virtualScrollContainer.scrollTo(5);
2135-
await wait(30);
2135+
await firstValueFrom(combo.virtualScrollContainer.chunkLoad);
21362136
fixture.detectChanges();
21372137
selectedItem = fixture.debugElement.query(By.css(`.${CSS_CLASS_SELECTED}`));
21382138
expect(selectedItem.nativeElement.textContent).toEqual(selectedItemText);

projects/igniteui-angular/src/lib/grids/common/crud.service.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -258,8 +258,10 @@ export class IgxCellCrudState {
258258
let activeElement;
259259
if (cellNode) {
260260
const document = cellNode.getRootNode() as Document | ShadowRoot;
261-
activeElement = document.activeElement as HTMLElement;
262-
activeElement.blur();
261+
if (cellNode.contains(document.activeElement)) {
262+
activeElement = document.activeElement as HTMLElement;
263+
this.grid.tbody.nativeElement.focus();
264+
}
263265
}
264266

265267
const formControl = this.grid.validation.getFormControl(this.cell.id.rowID, this.cell.column.field);

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

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3606,16 +3606,14 @@ export abstract class IgxGridBaseDirective implements GridType,
36063606
public _setupListeners() {
36073607
const destructor = takeUntil<any>(this.destroy$);
36083608
fromEvent(this.nativeElement, 'focusout').pipe(filter(() => !!this.navigation.activeNode), destructor).subscribe((event) => {
3609-
if (!this.crudService.cell &&
3610-
!!this.navigation.activeNode &&
3611-
((event.target === this.tbody.nativeElement && this.navigation.activeNode.row >= 0 &&
3612-
this.navigation.activeNode.row < this.dataView.length)
3613-
|| (event.target === this.theadRow.nativeElement && this.navigation.activeNode.row === -1)
3614-
|| (event.target === this.tfoot.nativeElement && this.navigation.activeNode.row === this.dataView.length)) &&
3609+
const activeNode = this.navigation.activeNode;
3610+
if (!this.crudService.cell && !!activeNode &&
3611+
((event.target === this.tbody.nativeElement && activeNode.row >= 0 &&
3612+
activeNode.row < this.dataView.length)
3613+
|| (event.target === this.theadRow.nativeElement && activeNode.row === -1)
3614+
|| (event.target === this.tfoot.nativeElement && activeNode.row === this.dataView.length)) &&
36153615
!(this.rowEditable && this.crudService.rowEditingBlocked && this.crudService.rowInEditMode)) {
3616-
this.navigation.lastActiveNode = this.navigation.activeNode;
3617-
this.navigation.activeNode = {} as IActiveNode;
3618-
this.notifyChanges();
3616+
this.clearActiveNode();
36193617
}
36203618
});
36213619
this.rowAddedNotifier.pipe(destructor).subscribe(args => this.refreshGridState(args));
@@ -6067,10 +6065,7 @@ export abstract class IgxGridBaseDirective implements GridType,
60676065
return true;
60686066
}
60696067

6070-
const activeCell = this.gridAPI.grid.navigation.activeNode;
6071-
if (activeCell && activeCell.row !== -1) {
6072-
this.tbody.nativeElement.focus();
6073-
}
6068+
this.navigation.restoreActiveNodeFocus();
60746069
}
60756070

60766071
/**
@@ -6257,7 +6252,20 @@ export abstract class IgxGridBaseDirective implements GridType,
62576252
// TODO: do not remove this, as it is used in rowEditTemplate, but mark is as internal and hidden
62586253
/* blazorCSSuppress */
62596254
public endEdit(commit = true, event?: Event): boolean {
6260-
return this.crudService.endEdit(commit, event);
6255+
const document = this.nativeElement?.getRootNode() as Document | ShadowRoot;
6256+
const focusWithin = this.nativeElement?.contains(document.activeElement);
6257+
6258+
const success = this.crudService.endEdit(commit, event);
6259+
6260+
if (focusWithin) {
6261+
// restore focus for navigation
6262+
this.navigation.restoreActiveNodeFocus();
6263+
} else if (this.navigation.activeNode) {
6264+
// grid already lost focus, clear active node
6265+
this.clearActiveNode();
6266+
}
6267+
6268+
return success;
62616269
}
62626270

62636271
/**
@@ -7842,4 +7850,13 @@ export abstract class IgxGridBaseDirective implements GridType,
78427850
if (!newData || !newData.length) return false;
78437851
return Object.keys(oldData[0]).join() !== Object.keys(newData[0]).join();
78447852
}
7853+
7854+
/**
7855+
* Clears the current navigation service active node
7856+
*/
7857+
private clearActiveNode() {
7858+
this.navigation.lastActiveNode = this.navigation.activeNode;
7859+
this.navigation.activeNode = {} as IActiveNode;
7860+
this.notifyChanges();
7861+
}
78457862
}

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

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,23 @@ export class IgxGridNavigationService {
339339
return isChanged;
340340
}
341341

342+
/** Focus the Grid section (header, body, footer) depending on the current activeNode */
343+
public restoreActiveNodeFocus() {
344+
if (!this.activeNode || !Object.keys(this.activeNode).length) {
345+
return;
346+
}
347+
348+
if (this.activeNode.row >= 0 && this.activeNode.row < this.grid.dataView.length) {
349+
this.grid.tbody.nativeElement.focus();
350+
}
351+
if (this.activeNode.row === -1) {
352+
this.grid.theadRow.nativeElement.focus();
353+
}
354+
if (this.activeNode.row === this.grid.dataView.length) {
355+
this.grid.tfoot.nativeElement.focus();
356+
}
357+
}
358+
342359
protected getNextPosition(rowIndex: number, colIndex: number, key: string, shift: boolean, ctrl: boolean, event: KeyboardEvent) {
343360
if (!this.isDataRow(rowIndex, true) && (key.indexOf('down') < 0 || key.indexOf('up') < 0) && ctrl) {
344361
return { rowIndex, colIndex };

0 commit comments

Comments
 (0)