Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand Down Expand Up @@ -78,6 +92,16 @@ export class IgxSimpleComboComponent extends IgxComboBaseDirective implements Co
@Output()
public selectionChanging = new EventEmitter<ISimpleComboSelectionChangingEventArgs>();

/**
* Emitted when item selection is changed, after the selection completes
*
* ```html
* <igx-simple-combo (selectionChanged)='handleSelection()'></igx-simple-combo>
* ```
*/
@Output()
public selectionChanged = new EventEmitter<ISimpleComboSelectionChangedEventArgs>();

@ViewChild(IgxTextSelectionDirective, { static: true })
private textSelection: IgxTextSelectionDirective;

Expand Down Expand Up @@ -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);
Expand Down
Loading