diff --git a/CHANGELOG.md b/CHANGELOG.md index db4196e3639..fc067123e7a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -52,6 +52,9 @@ All notable changes for each version of this project will be documented in this - The overlay service now uses the Popover API to place overlay elements in the top layer, eliminating z-index stacking issues. - Improved positioning accuracy for container-based overlays with fixed container bounds. +- `IgxSimpleCombo` + - Introduced `selectionChanged` event. This event is non-cancelable and fires only after the selection is successful. + - **AI-Assisted Development - Copilot Skills** - Three consolidated Copilot Skills are now included in the repository to teach AI coding assistants/agents (e.g., GitHub Copilot, Cursor, Windsurf, Claude, JetBrains AI, etc.) how to work with Ignite UI for Angular: - **Components** - UI Components (form controls, layout, data display, feedback/overlays, directives — Input Group, Combo, Select, Date/Time Pickers, Calendar, Tabs, Stepper, Accordion, List, Card, Dialog, Snackbar, Button, Ripple, Tooltip, Drag and Drop, Layout Manager, Dock Manager and Charts (Area Chart, Bar Chart, Column Chart, Stock/Financial Chart, Pie Chart)) diff --git a/projects/igniteui-angular/simple-combo/src/simple-combo/simple-combo.component.spec.ts b/projects/igniteui-angular/simple-combo/src/simple-combo/simple-combo.component.spec.ts index 2c29c9a95d2..11dcd6faf08 100644 --- a/projects/igniteui-angular/simple-combo/src/simple-combo/simple-combo.component.spec.ts +++ b/projects/igniteui-angular/simple-combo/src/simple-combo/simple-combo.component.spec.ts @@ -256,6 +256,65 @@ describe('IgxSimpleCombo', () => { cancel: false }); }); + it('should fire selectionChanged event after item selection completes', () => { + const dropdown = jasmine.createSpyObj('IgxComboDropDownComponent', ['selectItem']); + combo.ngOnInit(); + combo.data = data; + combo.dropdown = dropdown; + const comboInput = jasmine.createSpyObj('IgxInputDirective', ['value']); + comboInput.value = 'test'; + combo.comboInput = comboInput; + spyOnProperty(combo, 'totalItemCount').and.returnValue(combo.data.length); + spyOn(combo.selectionChanged, 'emit'); + + let oldSelection = undefined; + let newSelection = combo.data[1]; + + combo.select(combo.data[1]); + expect(combo.selectionChanged.emit).toHaveBeenCalledTimes(1); + expect(combo.selectionChanged.emit).toHaveBeenCalledWith({ + oldValue: undefined, + newValue: newSelection, + oldSelection: undefined, + newSelection: newSelection, + owner: combo, + displayText: newSelection.trim() + }); + + oldSelection = newSelection; + newSelection = combo.data[0]; + combo.select(combo.data[0]); + expect(combo.selectionChanged.emit).toHaveBeenCalledTimes(2); + expect(combo.selectionChanged.emit).toHaveBeenCalledWith({ + oldValue: oldSelection, + newValue: newSelection, + oldSelection: oldSelection, + newSelection: newSelection, + owner: combo, + displayText: newSelection.trim() + }); + }); + it('should not fire selectionChanged event when selectionChanging is cancelled', () => { + const dropdown = jasmine.createSpyObj('IgxComboDropDownComponent', ['selectItem']); + combo.ngOnInit(); + combo.data = data; + combo.dropdown = dropdown; + const comboInput = jasmine.createSpyObj('IgxInputDirective', ['value']); + comboInput.value = 'test'; + combo.comboInput = comboInput; + spyOnProperty(combo, 'totalItemCount').and.returnValue(combo.data.length); + + spyOn(combo.selectionChanging, 'emit').and.callFake((event: ISimpleComboSelectionChangingEventArgs) => { + event.cancel = true; + }); + spyOn(combo.selectionChanged, 'emit'); + + combo.select(combo.data[0]); + + expect(combo.selectionChanging.emit).toHaveBeenCalledTimes(1); + expect(combo.selectionChanged.emit).not.toHaveBeenCalled(); + expect(combo.selection).toEqual(undefined); + }); it('should properly emit added and removed values in change event on single value selection', () => { const dropdown = jasmine.createSpyObj('IgxComboDropDownComponent', ['selectItem']); combo.ngOnInit(); diff --git a/projects/igniteui-angular/simple-combo/src/simple-combo/simple-combo.component.ts b/projects/igniteui-angular/simple-combo/src/simple-combo/simple-combo.component.ts index aa73c06b7c7..635b7da5b50 100644 --- a/projects/igniteui-angular/simple-combo/src/simple-combo/simple-combo.component.ts +++ b/projects/igniteui-angular/simple-combo/src/simple-combo/simple-combo.component.ts @@ -27,6 +27,20 @@ export interface ISimpleComboSelectionChangingEventArgs extends CancelableEventA displayText: string; } +/** Emitted when an igx-simple-combo's selection has been changed. */ +export interface ISimpleComboSelectionChangedEventArgs extends IBaseEventArgs { + /** An object which represents the value that was previously selected */ + oldValue: any; + /** An object which represents the value that is currently selected */ + newValue: any; + /** An object which represents the item that was previously selected */ + oldSelection: any; + /** An object which represents the item that is currently selected */ + newSelection: any; + /** The text that is displayed in the combo text box */ + displayText: string; +} + /** * Represents a drop-down list that provides filtering functionality, allowing users to choose a single option from a predefined list. * @@ -78,6 +92,16 @@ export class IgxSimpleComboComponent extends IgxComboBaseDirective implements Co @Output() public selectionChanging = new EventEmitter(); + /** + * Emitted when item selection is changed, after the selection completes + * + * ```html + * + * ``` + */ + @Output() + public selectionChanged = new EventEmitter(); + @ViewChild(IgxTextSelectionDirective, { static: true }) private textSelection: IgxTextSelectionDirective; @@ -515,6 +539,17 @@ export class IgxSimpleComboComponent extends IgxComboBaseDirective implements Co : this.createDisplayText(super.selection, [args.oldValue]); } this._onChangeCallback(args.newValue); + if (args.newSelection !== args.oldSelection) { + const changedArgs: ISimpleComboSelectionChangedEventArgs = { + newValue: args.newValue, + oldValue: args.oldValue, + newSelection: args.newSelection, + oldSelection: args.oldSelection, + displayText: this._displayValue, + owner: this + }; + this.selectionChanged.emit(changedArgs); + } this._updateInput = true; } else if (this.isRemote) { this.registerRemoteEntries(newValueAsArray, false);