Skip to content

Commit 53eccd6

Browse files
authored
Merge branch '16.1.x' into mkirkova/fix-14189-16.1.x
2 parents c6ce8c8 + 84c6ff9 commit 53eccd6

File tree

14 files changed

+262
-38
lines changed

14 files changed

+262
-38
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ All notable changes for each version of this project will be documented in this
77
- `IgxButtonGroup`:
88
- Reverted cancellable on `selected` and `deselected` events (added in 15.1.24) as it was breaking firing order and related handling.
99

10+
### General
11+
- `IgxSimpleCombo`
12+
- **Behavioral Change** When bound to `ngModel` and `formControlName` directives, the model would not be updated when the user types into the input and will only be updated on selection.
13+
1014
## 16.1.4
1115
### New Features
1216
- `Themes`:

projects/igniteui-angular/src/lib/directives/for-of/for_of.directive.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -904,6 +904,19 @@ export class IgxForOfDirective<T, U extends T[] = T[]> implements OnInit, OnChan
904904
}
905905
}
906906

907+
908+
/**
909+
* @hidden
910+
* @internal
911+
*/
912+
public updateScroll(): void {
913+
if (this.igxForScrollOrientation === "horizontal") {
914+
const scrollAmount = this.scrollComponent.nativeElement["scrollLeft"];
915+
this.scrollComponent.scrollAmount = scrollAmount;
916+
this._updateScrollOffset();
917+
}
918+
}
919+
907920
protected updateSizes() {
908921
if (!this.scrollComponent.nativeElement.isConnected) return;
909922
const scrollable = this.isScrollable();

projects/igniteui-angular/src/lib/directives/tooltip/tooltip-target.directive.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ export class IgxTooltipTargetDirective extends IgxToggleActionDirective implemen
100100
*/
101101
@Input('igxTooltipTarget')
102102
public override set target(target: any) {
103-
if (target !== null && target !== '') {
103+
if (target instanceof IgxTooltipDirective) {
104104
this._target = target;
105105
}
106106
}

projects/igniteui-angular/src/lib/directives/tooltip/tooltip.directive.spec.ts

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { fakeAsync, TestBed, tick, flush, waitForAsync } from '@angular/core/testing';
22
import { By } from '@angular/platform-browser';
33
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
4-
import { IgxTooltipSingleTargetComponent, IgxTooltipMultipleTargetsComponent, IgxTooltipPlainStringComponent } from '../../test-utils/tooltip-components.spec';
4+
import { IgxTooltipSingleTargetComponent, IgxTooltipMultipleTargetsComponent, IgxTooltipPlainStringComponent, IgxTooltipWithToggleActionComponent } from '../../test-utils/tooltip-components.spec';
55
import { UIInteractions } from '../../test-utils/ui-interactions.spec';
66
import { configureTestSuite } from '../../test-utils/configure-suite';
77
import { HorizontalAlignment, VerticalAlignment, AutoPositionStrategy } from '../../services/public_api';
@@ -24,7 +24,8 @@ describe('IgxTooltip', () => {
2424
NoopAnimationsModule,
2525
IgxTooltipSingleTargetComponent,
2626
IgxTooltipMultipleTargetsComponent,
27-
IgxTooltipPlainStringComponent
27+
IgxTooltipPlainStringComponent,
28+
IgxTooltipWithToggleActionComponent
2829
]
2930
}).compileComponents();
3031
UIInteractions.clearOverlay();
@@ -554,6 +555,36 @@ describe('IgxTooltip', () => {
554555
verifyTooltipPosition(tooltipNativeElement, buttonOne, false);
555556
}));
556557
});
558+
559+
describe('Tooltip integration', () => {
560+
beforeEach(waitForAsync(() => {
561+
fix = TestBed.createComponent(IgxTooltipWithToggleActionComponent);
562+
fix.detectChanges();
563+
tooltipNativeElement = fix.debugElement.query(By.directive(IgxTooltipDirective)).nativeElement;
564+
tooltipTarget = fix.componentInstance.tooltipTarget as IgxTooltipTargetDirective;
565+
button = fix.debugElement.query(By.directive(IgxTooltipTargetDirective));
566+
}));
567+
568+
it('Correctly sets tooltip target when defined before igxToggleAction directive on same host - issue #14196', fakeAsync(() => {
569+
expect(tooltipTarget.target.element).toBe(tooltipNativeElement);
570+
expect(fix.componentInstance.toggleDir.collapsed).toBe(true);
571+
572+
hoverElement(button);
573+
flush();
574+
575+
verifyTooltipVisibility(tooltipNativeElement, tooltipTarget, true);
576+
577+
UIInteractions.simulateClickEvent(button.nativeElement);
578+
fix.detectChanges();
579+
580+
verifyTooltipVisibility(tooltipNativeElement, tooltipTarget, false);
581+
582+
UIInteractions.simulateClickEvent(button.nativeElement);
583+
fix.detectChanges();
584+
585+
expect(fix.componentInstance.toggleDir.collapsed).toBe(false);
586+
}));
587+
});
557588
});
558589

559590
const hoverElement = (element) => element.nativeElement.dispatchEvent(new MouseEvent('mouseenter'));

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

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3592,6 +3592,7 @@ export abstract class IgxGridBaseDirective extends DisplayDensityBase implements
35923592
// the vert. scrollbar showing/hiding
35933593
this.notifyChanges(true);
35943594
this.cdr.detectChanges();
3595+
Promise.resolve().then(() => this.headerContainer.updateScroll());
35953596
});
35963597

35973598
this.verticalScrollContainer.contentSizeChange.pipe(filter(() => !this._init), throttleTime(30), destructor).subscribe(() => {
@@ -6257,12 +6258,8 @@ export abstract class IgxGridBaseDirective extends DisplayDensityBase implements
62576258
// in case state is no longer valid - update it.
62586259
const rowForOf = row.virtDirRow;
62596260
const gridScrLeft = rowForOf.getScroll().scrollLeft;
6260-
const left = -parseInt(rowForOf.dc.instance._viewContainer.element.nativeElement.style.left, 10);
6261-
const actualScrollLeft = left + rowForOf.getColumnScrollLeft(rowForOf.state.startIndex);
6262-
if (gridScrLeft !== actualScrollLeft) {
6263-
rowForOf.onHScroll(gridScrLeft);
6264-
rowForOf.cdr.detectChanges();
6265-
}
6261+
rowForOf.onHScroll(gridScrLeft);
6262+
rowForOf.cdr.detectChanges();
62666263
}
62676264

62686265
protected changeRowEditingOverlayStateOnScroll(row: RowType) {
@@ -6801,7 +6798,7 @@ export abstract class IgxGridBaseDirective extends DisplayDensityBase implements
68016798
let res = !parentElement ||
68026799
parentElement.clientHeight === 0 ||
68036800
parentElement.clientHeight === renderedHeight;
6804-
if ((!this.platform.isChromium && !this.platform.isFirefox) || this._autoSize) {
6801+
if (parentElement && (res || this._autoSize)) {
68056802
// If grid causes the parent container to extend (for example when container is flex)
68066803
// we should always auto-size since the actual size of the container will continuously change as the grid renders elements.
68076804
this._autoSize = false;

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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2600,7 +2600,7 @@ describe('IgxGrid - Filtering Row UI actions #grid', () => {
26002600
}));
26012601

26022602
it('should position filter row and chips correctly when grid has column groups and one is hidden.',
2603-
fakeAsync(() => {
2603+
(async() => {
26042604
const filteringExpressionsTree = new FilteringExpressionsTree(FilteringLogic.And, 'ProductName');
26052605
const expression = {
26062606
fieldName: 'ProductName',
@@ -2622,7 +2622,8 @@ describe('IgxGrid - Filtering Row UI actions #grid', () => {
26222622

26232623
GridFunctions.clickFilterCellChip(fix, 'AnotherField');
26242624
fix.detectChanges();
2625-
2625+
await wait(30);
2626+
fix.detectChanges();
26262627
// check if it is positioned at the bottom of the thead.
26272628
const theadWrapper = grid.theadRow.nativeElement.firstElementChild;
26282629
const filteringRow = fix.debugElement.query(By.directive(IgxGridFilteringRowComponent));
@@ -5450,7 +5451,7 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => {
54505451
fix.detectChanges();
54515452
expect(listItems[0].classList.contains("igx-list__item-base--active")).toBeFalse();
54525453
expect(listItems[1].classList.contains("igx-list__item-base--active")).toBeTrue();
5453-
5454+
54545455
// on arrow up the first item should be active again
54555456
UIInteractions.triggerKeyDownEvtUponElem('arrowup', list, true);
54565457
fix.detectChanges();

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

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1442,6 +1442,20 @@ describe('IgxGrid Component Tests #grid', () => {
14421442
fix.componentInstance.data = fix.componentInstance.fullData;
14431443
}));
14441444

1445+
it('should not auto-size when container has display:contents and size is determinable ', fakeAsync(() => {
1446+
const fix = TestBed.createComponent(IgxGridWrappedInContComponent);
1447+
fix.componentInstance.display = "contents";
1448+
fix.componentInstance.data = fix.componentInstance.fullData;
1449+
tick();
1450+
fix.detectChanges();
1451+
const defaultHeight = fix.debugElement.query(By.css(TBODY_CLASS)).styles.height;
1452+
const defaultHeightNum = parseInt(defaultHeight, 10);
1453+
expect(defaultHeight).not.toBeFalsy();
1454+
1455+
expect(defaultHeightNum).toBeGreaterThan(fix.componentInstance.grid.renderedRowHeight * 10);
1456+
expect(fix.componentInstance.grid.calcHeight).toBeGreaterThan(fix.componentInstance.grid.renderedRowHeight * 10);
1457+
}));
1458+
14451459
it('should render correct columns if after scrolling right container size changes so that all columns become visible.',
14461460
async () => {
14471461
const fix = TestBed.createComponent(IgxGridDefaultRenderingComponent);
@@ -2955,7 +2969,7 @@ export class IgxGridWithCustomFooterComponent extends IgxGridTestComponent {
29552969
public override data = SampleTestData.foodProductData();
29562970
}
29572971
@Component({
2958-
template: `<div [style.width.px]="outerWidth" [style.height.px]="outerHeight">
2972+
template: `<div [style.display]="display" [style.width.px]="outerWidth" [style.height.px]="outerHeight">
29592973
<igx-grid #grid [data]="data" [displayDensity]="density" [autoGenerate]="true">
29602974
<igx-paginator *ngIf="paging" [perPage]="pageSize"></igx-paginator>
29612975
</igx-grid>
@@ -3006,6 +3020,7 @@ export class IgxGridWrappedInContComponent extends IgxGridTestComponent {
30063020
public density: DisplayDensity = DisplayDensity.comfortable;
30073021
public outerWidth = 800;
30083022
public outerHeight: number;
3023+
public display = "";
30093024
}
30103025

30113026
@Component({

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

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1525,6 +1525,34 @@ describe('IgxSimpleCombo', () => {
15251525
expect(combo.filteredData.length).toBeLessThan(combo.data.length)
15261526
expect(combo.filteredData[0].field).toBe(target.value)
15271527
});
1528+
1529+
it('should prevent Enter key default behavior when filtering data', fakeAsync(() => {
1530+
const keyEvent = new KeyboardEvent('keydown', { key: 'Enter' });
1531+
const spy = spyOn(keyEvent, 'preventDefault');
1532+
1533+
expect(combo.collapsed).toBe(true);
1534+
expect(combo.selection.length).toEqual(0);
1535+
1536+
input.triggerEventHandler('focus', {});
1537+
UIInteractions.simulateTyping('c', input);
1538+
fixture.detectChanges();
1539+
1540+
expect(combo.collapsed).toBe(false);
1541+
1542+
combo.handleKeyDown(keyEvent);
1543+
tick();
1544+
fixture.detectChanges();
1545+
1546+
expect(combo.selection.length).toEqual(1);
1547+
expect(combo.collapsed).toBe(true);
1548+
expect(spy).toHaveBeenCalled();
1549+
1550+
combo.handleKeyDown(keyEvent);
1551+
tick();
1552+
fixture.detectChanges();
1553+
1554+
expect(spy).toHaveBeenCalledTimes(1);
1555+
}));
15281556
});
15291557

15301558
describe('Display density', () => {
@@ -1809,6 +1837,45 @@ describe('IgxSimpleCombo', () => {
18091837
expect(combo.valid).toEqual(IgxComboState.INVALID);
18101838
expect(combo.comboInput.valid).toEqual(IgxInputState.INVALID);
18111839
});
1840+
1841+
it('Should update the model only if a selection is changing otherwise it should be undefiend when the user is filtering in templeted form', fakeAsync(() => {
1842+
input = fixture.debugElement.query(By.css(`.${CSS_CLASS_COMBO_INPUTGROUP}`));
1843+
let model;
1844+
1845+
combo.open();
1846+
fixture.detectChanges();
1847+
const item2 = fixture.debugElement.queryAll(By.css(`.${CSS_CLASS_DROPDOWNLISTITEM}`))[3];
1848+
item2.triggerEventHandler('click', UIInteractions.getMouseEvent('click'));
1849+
fixture.detectChanges();
1850+
model = fixture.componentInstance.values;
1851+
1852+
expect(combo.displayValue).toEqual(['Illinois']);
1853+
expect(combo.value).toEqual(['Illinois']);
1854+
expect(model).toEqual('Illinois');
1855+
1856+
combo.deselect();
1857+
fixture.detectChanges();
1858+
model = fixture.componentInstance.values;
1859+
1860+
expect(combo.selection).toEqual([]);
1861+
expect(model).toEqual(undefined);
1862+
expect(combo.displayValue).toEqual([]);
1863+
1864+
combo.focusSearchInput();
1865+
UIInteractions.simulateTyping('con', input);
1866+
fixture.detectChanges();
1867+
model = fixture.componentInstance.values;
1868+
expect(combo.comboInput.value).toEqual('con');
1869+
expect(model).toEqual(undefined);
1870+
1871+
UIInteractions.triggerKeyDownEvtUponElem('Enter', input.nativeElement);
1872+
fixture.detectChanges();
1873+
model = fixture.componentInstance.values;
1874+
expect(combo.selection).toBeDefined()
1875+
expect(combo.displayValue).toEqual(['Wisconsin']);
1876+
expect(combo.value).toEqual(['Wisconsin']);
1877+
expect(model).toEqual('Wisconsin');
1878+
}));
18121879
});
18131880
describe('Reactive form tests: ', () => {
18141881
beforeAll(waitForAsync(() => {
@@ -2026,6 +2093,43 @@ describe('IgxSimpleCombo', () => {
20262093
expect((combo as any).inputGroup.element.nativeElement.classList.contains(CSS_CLASS_INPUT_GROUP_INVALID)).toBe(true);
20272094
expect((combo as any).inputGroup.element.nativeElement.classList.contains(CSS_CLASS_INPUT_GROUP_REQUIRED)).toBe(false);
20282095
}));
2096+
2097+
it('Should update the model only if a selection is changing otherwise it should be undefiend when the user is filtering in reactive form', fakeAsync(() => {
2098+
const form = (fixture.componentInstance as IgxSimpleComboInReactiveFormComponent).comboForm;
2099+
input = fixture.debugElement.query(By.css(`.${CSS_CLASS_COMBO_INPUTGROUP}`));
2100+
2101+
combo.open();
2102+
fixture.detectChanges();
2103+
2104+
const item2 = fixture.debugElement.queryAll(By.css(`.${CSS_CLASS_DROPDOWNLISTITEM}`))[3];
2105+
item2.triggerEventHandler('click', UIInteractions.getMouseEvent('click'));
2106+
fixture.detectChanges();
2107+
2108+
2109+
expect(combo.displayValue).toEqual(['Four']);
2110+
expect(combo.value).toEqual([4]);
2111+
expect(form.controls['comboValue'].value).toEqual(4);
2112+
2113+
combo.deselect();
2114+
fixture.detectChanges();
2115+
2116+
expect(combo.selection).toEqual([]);
2117+
expect(form.controls['comboValue'].value).toEqual(undefined);
2118+
expect(combo.displayValue).toEqual([]);
2119+
2120+
combo.focusSearchInput();
2121+
UIInteractions.simulateTyping('on', input);
2122+
fixture.detectChanges();
2123+
expect(combo.comboInput.value).toEqual('on');
2124+
expect(form.controls['comboValue'].value).toEqual(undefined);
2125+
2126+
combo.select(combo.data[0][combo.valueKey]);
2127+
fixture.detectChanges();
2128+
expect(combo.selection).toBeDefined();
2129+
expect(combo.displayValue).toEqual(['One']);
2130+
expect(combo.value).toEqual([1]);
2131+
expect(form.controls['comboValue'].value).toEqual(1);
2132+
}));
20292133
});
20302134
});
20312135

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

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,6 @@ export class IgxSimpleComboComponent extends IgxComboBaseDirective implements Co
260260
if (event !== undefined) {
261261
this.filterValue = this.searchValue = typeof event === 'string' ? event : event.target.value;
262262
}
263-
this._onChangeCallback(this.searchValue);
264263
if (this.collapsed && this.comboInput.focused) {
265264
this.open();
266265
}
@@ -296,10 +295,12 @@ export class IgxSimpleComboComponent extends IgxComboBaseDirective implements Co
296295
if (filtered === null || filtered === undefined) {
297296
return;
298297
}
299-
this.select(this.dropdown.focusedItem.itemID);
300-
event.preventDefault();
301-
event.stopPropagation();
302-
this.close();
298+
if (!this.dropdown.collapsed) {
299+
this.select(this.dropdown.focusedItem.itemID);
300+
event.preventDefault();
301+
event.stopPropagation();
302+
this.close();
303+
}
303304
// manually trigger text selection as it will not be triggered during editing
304305
this.textSelection.trigger();
305306
return;

0 commit comments

Comments
 (0)