diff --git a/projects/igniteui-angular/src/lib/combo/combo.common.ts b/projects/igniteui-angular/src/lib/combo/combo.common.ts
index 91cf7852566..d2e1075b2cf 100644
--- a/projects/igniteui-angular/src/lib/combo/combo.common.ts
+++ b/projects/igniteui-angular/src/lib/combo/combo.common.ts
@@ -167,7 +167,27 @@ export abstract class IgxComboBaseDirective implements IgxComboBase, AfterViewCh
*/
@HostBinding('attr.id')
@Input()
- public id = `igx-combo-${NEXT_ID++}`;
+ public get id(): string {
+ return this._id;
+ }
+
+ public set id(value: string) {
+ if (!value) {
+ return;
+ }
+ const selection = this.selectionService.get(this._id);
+ this._id = value;
+ if (selection) {
+ this.selectionService.set(this._id, selection);
+ }
+ if (this.dropdown.open) {
+ this.dropdown.close();
+ }
+ if (this.inputGroup?.isFocused) {
+ this.inputGroup.element.nativeElement.blur();
+ this.inputGroup.isFocused = false;
+ }
+ }
/**
* Sets the style width of the element
@@ -943,6 +963,7 @@ export abstract class IgxComboBaseDirective implements IgxComboBase, AfterViewCh
protected compareCollator = new Intl.Collator();
protected computedStyles;
+ private _id: string = `igx-combo-${NEXT_ID++}`;
private _type = null;
private _dataType = '';
private _itemHeight = null;
diff --git a/projects/igniteui-angular/src/lib/simple-combo/simple-combo.component.spec.ts b/projects/igniteui-angular/src/lib/simple-combo/simple-combo.component.spec.ts
index c3cecdffbff..1f93197de61 100644
--- a/projects/igniteui-angular/src/lib/simple-combo/simple-combo.component.spec.ts
+++ b/projects/igniteui-angular/src/lib/simple-combo/simple-combo.component.spec.ts
@@ -16,6 +16,8 @@ import { AbsoluteScrollStrategy, AutoPositionStrategy, ConnectedPositioningStrat
import { configureTestSuite } from '../test-utils/configure-suite';
import { UIInteractions, wait } from '../test-utils/ui-interactions.spec';
import { IgxSimpleComboComponent, ISimpleComboSelectionChangingEventArgs } from './public_api';
+import { IgxGridComponent } from '../grids/grid/grid.component';
+import { IGX_GRID_DIRECTIVES } from '../grids/grid/public_api';
const CSS_CLASS_COMBO = 'igx-combo';
@@ -2563,8 +2565,109 @@ describe('IgxSimpleCombo', () => {
expect(input.nativeElement.value).toEqual('Product 5');
}));
});
+
+ describe('Integration', () => {
+ let grid: IgxGridComponent;
+
+ beforeAll(waitForAsync(() => {
+ TestBed.configureTestingModule({
+ imports: [
+ NoopAnimationsModule,
+ IgxSimpleComboInGridComponent
+ ]
+ }).compileComponents();
+ }));
+ beforeEach(() => {
+ fixture = TestBed.createComponent(IgxSimpleComboInGridComponent);
+ fixture.detectChanges();
+ grid = fixture.componentInstance.grid;
+ });
+ it('Combo in IgxGrid cell display template correctly handles selection - issue #14305', async () => {
+ const firstRecRegionCell = grid.gridAPI.get_cell_by_index(0, 'Region') as any;
+ let comboNativeEl = firstRecRegionCell.nativeElement.querySelector(SIMPLE_COMBO_ELEMENT);
+ const comboToggleButton = comboNativeEl.querySelector(`.${CSS_CLASS_TOGGLEBUTTON}`);
+
+ UIInteractions.simulateClickEvent(comboToggleButton);
+ fixture.detectChanges();
+
+ const comboDropDownList = fixture.debugElement.query(By.css(`.${CSS_CLASS_DROPDOWNLIST}`));
+ const firstItem = comboDropDownList.nativeElement.querySelector(`.${CSS_CLASS_DROPDOWNLISTITEM}`);
+
+ UIInteractions.simulateClickEvent(firstItem);
+ fixture.detectChanges();
+
+ const firstRegionCellObject = grid.getCellByColumn(0, 'Region');
+ expect(firstRegionCellObject.value).toEqual(fixture.componentInstance.regions[0]);
+
+ try {
+ // combo should not throw from the selection getter at this point
+ grid.navigateTo(fixture.componentInstance.data.length - 1, 0);
+ await wait(30);
+ fixture.detectChanges();
+ } catch (error) {
+ fail(`Test failed with error: ${error}`)
+ }
+
+ const virtState = grid.verticalScrollContainer.state;
+ expect(virtState.startIndex).toBe(grid.dataView.length - virtState.chunkSize);
+
+ // These will fail in case the editor (combo) in the cell display template is not bound to the cell value
+ // as the first record's selected value will be applied on the reused combos bc of the virtualization
+ for (let i = virtState.startIndex; i < virtState.startIndex + virtState.chunkSize && i < grid.dataView.length; i++) {
+ const targetCell = grid.gridAPI.get_cell_by_index(i, 'Region') as any;
+ comboNativeEl = targetCell.nativeElement.querySelector(SIMPLE_COMBO_ELEMENT);
+ const comboInput = comboNativeEl.querySelector('input');
+ expect(comboInput.value).toBe('', `Failed on index: ${i.toString()}`);
+ }
+
+ for (let i = virtState.startIndex; i < virtState.startIndex + virtState.chunkSize && i < grid.dataView.length; i++) {
+ const cell = grid.getCellByColumn(i, 'Region');
+ expect(cell.value).toBe(undefined);
+ }
+ });
+ });
});
+@Component({
+ template: `
+
+
+
+
+
+
+
+
+
+
+
+
+ `,
+ standalone: true,
+ imports: [IgxSimpleComboComponent, IGX_GRID_DIRECTIVES, FormsModule]
+})
+class IgxSimpleComboInGridComponent {
+ @ViewChild('grid', { read: IgxGridComponent, static: true })
+ public grid: IgxGridComponent;
+
+ public data = [];
+ public regions = [];
+ constructor() {
+ for (let i = 1; i <= 15; i++) {
+ this.data.push({
+ ID: i,
+ region: undefined
+ });
+ }
+ for (let i = 1; i <= 5; i++) {
+ this.regions.push(`Region ${i}`);
+ }
+ }
+}
+
@Component({
template: `