From 7c1b211b3982882ce0bcbdd072c6066ba5be2a44 Mon Sep 17 00:00:00 2001 From: ddaribo Date: Thu, 13 Jun 2024 12:41:29 +0300 Subject: [PATCH 1/2] fix(combo): add test for selection with value key of array type --- .../src/lib/combo/combo.component.spec.ts | 78 +++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/projects/igniteui-angular/src/lib/combo/combo.component.spec.ts b/projects/igniteui-angular/src/lib/combo/combo.component.spec.ts index 86ad16e35ff..60c26871640 100644 --- a/projects/igniteui-angular/src/lib/combo/combo.component.spec.ts +++ b/projects/igniteui-angular/src/lib/combo/combo.component.spec.ts @@ -2342,6 +2342,55 @@ describe('igxCombo', () => { expect(combo.value).toEqual([]); expect(combo.displayValue).toEqual('Selected Count: 0'); }); + it('should handle selection for combo with array type value key correctly - issue #14103', () => { + fixture = TestBed.createComponent(ComboArrayTypeValueKeyComponent); + fixture.detectChanges(); + combo = fixture.componentInstance.combo; + input = fixture.debugElement.query(By.css(`.${CSS_CLASS_COMBO_INPUTGROUP}`)); + const items = fixture.componentInstance.items; + expect(combo).toBeDefined(); + + const selectionSpy = spyOn(combo.selectionChanging, 'emit'); + let expectedResults: IComboSelectionChangingEventArgs = { + newValue: [combo.data[1][combo.valueKey]], + oldValue: [], + newSelection: [combo.data[1]], + oldSelection: [], + added: [combo.data[1]], + removed: [], + event: undefined, + owner: combo, + displayText: `${combo.data[1][combo.displayKey]}`, + cancel: false + }; + + let expectedDisplayText = items[1][combo.displayKey]; + combo.select([fixture.componentInstance.items[1].value]); + fixture.detectChanges(); + + expect(selectionSpy).toHaveBeenCalledWith(expectedResults); + expect(input.nativeElement.value).toEqual(expectedDisplayText); + + expectedDisplayText = `${items[1][combo.displayKey]}, ${items[2][combo.displayKey]}`; + expectedResults = { + newValue: [combo.data[1][combo.valueKey], combo.data[2][combo.valueKey]], + oldValue: [combo.data[1][combo.valueKey]], + newSelection: [combo.data[1], combo.data[2]], + oldSelection: [combo.data[1]], + added: [combo.data[2]], + removed: [], + event: undefined, + owner: combo, + displayText: expectedDisplayText, + cancel: false + }; + + combo.select([items[2].value]); + fixture.detectChanges(); + + expect(selectionSpy).toHaveBeenCalledWith(expectedResults); + expect(input.nativeElement.value).toEqual(expectedDisplayText); + }); }); describe('Grouping tests: ', () => { beforeEach(() => { @@ -3797,3 +3846,32 @@ export class IgxComboBindingDataAfterInitComponent implements AfterViewInit { }, 1000); } } + +@Component({ + template: ` + `, + standalone: true, + imports: [IgxComboComponent] +}) +export class ComboArrayTypeValueKeyComponent { + @ViewChild(IgxComboComponent, { read: IgxComboComponent, static: true }) + public combo: IgxComboComponent; + public items: any[] = []; + + constructor() { + this.items = [ + { + item: "Item1", + value: [1, 2, 3] + }, + { + item: "Item2", + value: [4, 5, 6] + }, + { + item: "Item3", + value: [7, 8, 9] + } + ]; + } +} From 5c96fdd8ef429fd5e55c798bb30a27c5ab6159ab Mon Sep 17 00:00:00 2001 From: ddaribo Date: Thu, 13 Jun 2024 12:44:12 +0300 Subject: [PATCH 2/2] fix(combo): use isEqual to handle both complex types and NaN/falsy values --- projects/igniteui-angular/src/lib/combo/combo.common.ts | 7 +++---- projects/igniteui-angular/src/lib/core/utils.ts | 9 --------- 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/projects/igniteui-angular/src/lib/combo/combo.common.ts b/projects/igniteui-angular/src/lib/combo/combo.common.ts index 47ff7d5d10f..d35e161ace2 100644 --- a/projects/igniteui-angular/src/lib/combo/combo.common.ts +++ b/projects/igniteui-angular/src/lib/combo/combo.common.ts @@ -30,7 +30,7 @@ import { noop, Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; import { DisplayDensityBase, DisplayDensityToken, IDisplayDensityOptions } from '../core/density'; import { IgxSelectionAPIService } from '../core/selection'; -import { CancelableBrowserEventArgs, cloneArray, IBaseCancelableBrowserEventArgs, IBaseEventArgs, isNaNvalue, rem } from '../core/utils'; +import { CancelableBrowserEventArgs, cloneArray, IBaseCancelableBrowserEventArgs, IBaseEventArgs, rem } from '../core/utils'; import { SortingDirection } from '../data-operations/sorting-strategy'; import { IForOfState, IgxForOfDirective } from '../directives/for-of/for_of.directive'; import { IgxIconService } from '../icon/icon.service'; @@ -46,6 +46,7 @@ import { import { IComboItemAdditionEvent, IComboSearchInputEventArgs } from './public_api'; import { ComboResourceStringsEN, IComboResourceStrings } from '../core/i18n/combo-resources'; import { getCurrentResourceStrings } from '../core/i18n/resources'; +import { isEqual } from 'lodash-es'; export const IGX_COMBO_COMPONENT = /*@__PURE__*/new InjectionToken('IgxComboComponentToken'); @@ -1282,9 +1283,7 @@ export abstract class IgxComboBaseDirective extends DisplayDensityBase implement } return keys.map(key => { - const item = isNaNvalue(key) - ? this.data.find(entry => isNaNvalue(entry[this.valueKey])) - : this.data.find(entry => entry[this.valueKey] === key); + const item = this.data.find(entry => isEqual(entry[this.valueKey], key)); return item !== undefined ? item : { [this.valueKey]: key }; }); diff --git a/projects/igniteui-angular/src/lib/core/utils.ts b/projects/igniteui-angular/src/lib/core/utils.ts index c928eb0aa7b..bfc1b71f83f 100644 --- a/projects/igniteui-angular/src/lib/core/utils.ts +++ b/projects/igniteui-angular/src/lib/core/utils.ts @@ -226,15 +226,6 @@ export const isEqual = (obj1, obj2): boolean => { return obj1 === obj2; }; -/** - * Checks if provided variable is the value NaN - * - * @param value Value to check - * @returns true if provided variable is NaN - * @hidden - */ - export const isNaNvalue = (value: any): boolean => isNaN(value) && value !== undefined && typeof value !== 'string'; - /** * Utility service taking care of various utility functions such as * detecting browser features, general cross browser DOM manipulation, etc.