Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(combo, dropdown): emit owner in opening and closing events, #8326 #8347

Merged
merged 7 commits into from
Oct 13, 2020
4 changes: 2 additions & 2 deletions projects/igniteui-angular/src/lib/combo/README.md
Original file line number Diff line number Diff line change
@@ -336,9 +336,9 @@ Setting `[displayDensity]` affects the control's items' and inputs' css properti
| `onSearchInput` | Emitted when an the search input's input event is triggered | true | { searchValue: `string` } |
| `onAddition` | Emitted when an item is being added to the data collection | false | { oldCollection: `any[]`, addedItem: `<any>`, newCollection: `any[]` }|
| `onDataPreLoad` | Emitted when new chunk of data is loaded from the virtualization | false | { event: `Event` } |
| `onOpening` | Emitted before the dropdown is opened | false | { event: `Event` } |
| `onOpening` | Emitted before the dropdown is opened | false | `CancelableBrowserEventArgs & IBaseEventArgs` |
| `onOpened` | Emitted after the dropdown is opened | false | { event: `Event` } |
| `onClosing` | Emitted before the dropdown is closed | false | { event: `Event` } |
| `onClosing` | Emitted before the dropdown is closed | false | `CancelableBrowserEventArgs & IBaseEventArgs` |
| `onClosed` | Emitted after the dropdown is closed | false | { event: `Event` } |

### Methods
69 changes: 60 additions & 9 deletions projects/igniteui-angular/src/lib/combo/combo.component.spec.ts
Original file line number Diff line number Diff line change
@@ -19,6 +19,7 @@ import { DisplayDensity } from '../core/density';
import { AbsoluteScrollStrategy, ConnectedPositioningStrategy } from '../services/public_api';
import { IgxSelectionAPIService } from '../core/selection';
import { IgxIconService } from '../icon/public_api';
import { CancelableBrowserEventArgs, IBaseEventArgs } from '../core/utils';

const CSS_CLASS_COMBO = 'igx-combo';
const CSS_CLASS_COMBO_DROPDOWN = 'igx-combo__drop-down';
@@ -282,6 +283,45 @@ describe('igxCombo', () => {
combo.selectItems([], true);
expect(combo.selectedItems()).toEqual([]);
});
it('should emit owner on `onOpening` and `onClosing`', () => {
combo = new IgxComboComponent(elementRef, mockCdr, mockSelection as any, mockComboService,
mockIconService, null, null, mockInjector);
spyOn(mockIconService, 'addSvgIconFromText').and.returnValue(null);
combo.ngOnInit();
spyOn(combo.onOpening, 'emit').and.callThrough();
spyOn(combo.onClosing, 'emit').and.callThrough();
const mockObj = {};
const inputEvent: CancelableBrowserEventArgs & IBaseEventArgs = {
cancel: false,
owner: mockObj,
};
combo.comboInput = <any>{
nativeElement: {
focus: () => {}
}
};
combo.handleOpening(inputEvent);
const expectedCall: CancelableBrowserEventArgs & IBaseEventArgs = Object.assign({}, inputEvent, { owner: combo });
expect(combo.onOpening.emit).toHaveBeenCalledWith(expectedCall);
expect(inputEvent.owner).toEqual(mockObj);
combo.handleClosing(inputEvent);
expect(combo.onClosing.emit).toHaveBeenCalledWith(expectedCall);
expect(inputEvent.owner).toEqual(mockObj);
let sub = combo.onOpening.subscribe((e: CancelableBrowserEventArgs & IBaseEventArgs) => {
e.cancel = true;
});
combo.handleOpening(inputEvent);
expect(inputEvent.cancel).toEqual(true);
sub.unsubscribe();
inputEvent.cancel = false;

sub = combo.onClosing.subscribe((e: CancelableBrowserEventArgs & IBaseEventArgs) => {
e.cancel = true;
});
combo.handleClosing(inputEvent);
expect(inputEvent.cancel).toEqual(true);
sub.unsubscribe();
});
it('should fire onSelectionChange event on item selection', () => {
const selectionService = new IgxSelectionAPIService();
combo = new IgxComboComponent(elementRef, mockCdr, selectionService, mockComboService,
@@ -299,12 +339,13 @@ describe('igxCombo', () => {

combo.selectItems(newSelection);
expect(combo.onSelectionChange.emit).toHaveBeenCalledTimes(1);
expect(combo.onSelectionChange.emit).toHaveBeenCalledWith({
expect(combo.onSelectionChange.emit).toHaveBeenCalledWith(<IComboSelectionChangeEventArgs>{
oldSelection: oldSelection,
newSelection: newSelection,
added: newSelection,
removed: [],
event: undefined,
owner: combo,
displayText: `${newSelection.join(', ')}`,
cancel: false
});
@@ -314,12 +355,13 @@ describe('igxCombo', () => {
oldSelection = [...newSelection];
newSelection.push(newItem);
expect(combo.onSelectionChange.emit).toHaveBeenCalledTimes(2);
expect(combo.onSelectionChange.emit).toHaveBeenCalledWith({
expect(combo.onSelectionChange.emit).toHaveBeenCalledWith(<IComboSelectionChangeEventArgs>{
oldSelection: oldSelection,
newSelection: newSelection,
removed: [],
added: [combo.data[3]],
event: undefined,
owner: combo,
displayText: `${newSelection.join(', ')}`,
cancel: false
});
@@ -328,12 +370,13 @@ describe('igxCombo', () => {
newSelection = [combo.data[0]];
combo.selectItems(newSelection, true);
expect(combo.onSelectionChange.emit).toHaveBeenCalledTimes(3);
expect(combo.onSelectionChange.emit).toHaveBeenCalledWith({
expect(combo.onSelectionChange.emit).toHaveBeenCalledWith(<IComboSelectionChangeEventArgs>{
oldSelection: oldSelection,
newSelection: newSelection,
removed: oldSelection,
added: newSelection,
event: undefined,
owner: combo,
displayText: `${newSelection.join(', ')}`,
cancel: false
});
@@ -344,12 +387,13 @@ describe('igxCombo', () => {
combo.deselectItems([newItem]);
expect(combo.selectedItems().length).toEqual(0);
expect(combo.onSelectionChange.emit).toHaveBeenCalledTimes(4);
expect(combo.onSelectionChange.emit).toHaveBeenCalledWith({
expect(combo.onSelectionChange.emit).toHaveBeenCalledWith(<IComboSelectionChangeEventArgs>{
oldSelection: oldSelection,
newSelection: newSelection,
removed: [combo.data[0]],
added: [],
event: undefined,
owner: combo,
displayText: `${newSelection.join(', ')}`,
cancel: false
});
@@ -372,6 +416,7 @@ describe('igxCombo', () => {
added: [combo.data[0][combo.valueKey]],
removed: [],
event: undefined,
owner: combo,
displayText: `${combo.data[0][combo.displayKey]}`,
cancel: false
};
@@ -408,6 +453,7 @@ describe('igxCombo', () => {
added: newSelection.map(e => e[combo.valueKey]),
removed: [],
event: undefined,
owner: combo,
displayText: `${newSelection.map(entry => entry[combo.displayKey]).join(', ')}`,
cancel: false
};
@@ -472,11 +518,12 @@ describe('igxCombo', () => {
combo.selectAllItems(true);
expect(combo.selectedItems()).toEqual(data);
expect(combo.onSelectionChange.emit).toHaveBeenCalledTimes(1);
expect(combo.onSelectionChange.emit).toHaveBeenCalledWith({
expect(combo.onSelectionChange.emit).toHaveBeenCalledWith(<IComboSelectionChangeEventArgs>{
oldSelection: [],
newSelection: data,
added: data,
removed: [],
owner: combo,
event: undefined,
displayText: `${combo.data.join(', ')}`,
cancel: false
@@ -485,11 +532,12 @@ describe('igxCombo', () => {
combo.deselectAllItems(true);
expect(combo.selectedItems()).toEqual([]);
expect(combo.onSelectionChange.emit).toHaveBeenCalledTimes(2);
expect(combo.onSelectionChange.emit).toHaveBeenCalledWith({
expect(combo.onSelectionChange.emit).toHaveBeenCalledWith(<IComboSelectionChangeEventArgs>{
oldSelection: data,
newSelection: [],
added: [],
removed: data,
owner: combo,
event: undefined,
displayText: '',
cancel: false
@@ -1879,12 +1927,13 @@ describe('igxCombo', () => {
expect(selectedItem_1.element.nativeElement.classList.contains(CSS_CLASS_SELECTED)).toBeTruthy();
expect(combo.onSelectionChange.emit).toHaveBeenCalledTimes(1);
expect(combo.onSelectionChange.emit).toHaveBeenCalledWith(
{
<IComboSelectionChangeEventArgs>{
newSelection: [selectedItem_1.value[combo.valueKey]],
oldSelection: [],
added: [selectedItem_1.value[combo.valueKey]],
removed: [],
event: UIInteractions.getMouseEvent('click'),
owner: combo,
displayText: selectedItem_1.value[combo.valueKey],
cancel: false
});
@@ -1896,12 +1945,13 @@ describe('igxCombo', () => {
expect(selectedItem_2.element.nativeElement.classList.contains(CSS_CLASS_SELECTED)).toBeTruthy();
expect(combo.onSelectionChange.emit).toHaveBeenCalledTimes(2);
expect(combo.onSelectionChange.emit).toHaveBeenCalledWith(
{
<IComboSelectionChangeEventArgs>{
newSelection: [selectedItem_1.value[combo.valueKey], selectedItem_2.value[combo.valueKey]],
oldSelection: [selectedItem_1.value[combo.valueKey]],
added: [selectedItem_2.value[combo.valueKey]],
removed: [],
event: UIInteractions.getMouseEvent('click'),
owner: combo,
displayText: selectedItem_1.value[combo.valueKey] + ', ' + selectedItem_2.value[combo.valueKey],
cancel: false
});
@@ -1914,12 +1964,13 @@ describe('igxCombo', () => {
expect(unselectedItem.element.nativeElement.classList.contains(CSS_CLASS_SELECTED)).toBeFalsy();
expect(combo.onSelectionChange.emit).toHaveBeenCalledTimes(3);
expect(combo.onSelectionChange.emit).toHaveBeenCalledWith(
{
<IComboSelectionChangeEventArgs>{
newSelection: [selectedItem_2.value[combo.valueKey]],
oldSelection: [selectedItem_1.value[combo.valueKey], selectedItem_2.value[combo.valueKey]],
added: [],
removed: [unselectedItem.value[combo.valueKey]],
event: UIInteractions.getMouseEvent('click'),
owner: combo,
displayText: selectedItem_2.value[combo.valueKey],
cancel: false
});
24 changes: 15 additions & 9 deletions projects/igniteui-angular/src/lib/combo/combo.component.ts
Original file line number Diff line number Diff line change
@@ -453,7 +453,7 @@ export class IgxComboComponent extends DisplayDensityBase implements IgxComboBas
* ```
*/
@Output()
public onOpening = new EventEmitter<CancelableEventArgs & IBaseEventArgs>();
public onOpening = new EventEmitter<CancelableBrowserEventArgs & IBaseEventArgs>();

/**
* Emitted after the dropdown is opened
@@ -513,7 +513,7 @@ export class IgxComboComponent extends DisplayDensityBase implements IgxComboBas
* ```
*/
@Output()
public onDataPreLoad = new EventEmitter<any>();
public onDataPreLoad = new EventEmitter<IForOfState>();

/**
* Gets/gets combo id.
@@ -1145,7 +1145,7 @@ export class IgxComboComponent extends DisplayDensityBase implements IgxComboBas
const newCollection = [...this.data];
newCollection.push(addedItem);
const args: IComboItemAdditionEvent = {
oldCollection, addedItem, newCollection
oldCollection, addedItem, newCollection, owner: this
};
this.onAddition.emit(args);
this.data.push(addedItem);
@@ -1238,8 +1238,9 @@ export class IgxComboComponent extends DisplayDensityBase implements IgxComboBas
this.manageRequiredAsterisk();
this.cdr.detectChanges();
}
this.virtDir.onChunkPreload.pipe(takeUntil(this.destroy$)).subscribe((e) => {
this.onDataPreLoad.emit(e);
this.virtDir.onChunkPreload.pipe(takeUntil(this.destroy$)).subscribe((e: IForOfState) => {
const eventArgs: IForOfState = Object.assign({}, e, { owner: this });
this.onDataPreLoad.emit(eventArgs);
});
}

@@ -1489,6 +1490,7 @@ export class IgxComboComponent extends DisplayDensityBase implements IgxComboBas
added,
removed,
event,
owner: this,
displayText,
cancel: false
};
@@ -1549,8 +1551,10 @@ export class IgxComboComponent extends DisplayDensityBase implements IgxComboBas
* @hidden
* @internal
*/
public handleOpening(event: CancelableEventArgs) {
this.onOpening.emit(event);
public handleOpening(event: CancelableBrowserEventArgs & IBaseEventArgs) {
Lipata marked this conversation as resolved.
Show resolved Hide resolved
const eventArgs: CancelableBrowserEventArgs & IBaseEventArgs = Object.assign({}, event, { owner: this });
this.onOpening.emit(eventArgs);
event.cancel = eventArgs.cancel;
if (event.cancel) {
Lipata marked this conversation as resolved.
Show resolved Hide resolved
return;
}
@@ -1576,8 +1580,10 @@ export class IgxComboComponent extends DisplayDensityBase implements IgxComboBas
/**
* @hidden @internal
*/
public handleClosing(event) {
this.onClosing.emit(event);
public handleClosing(event: CancelableBrowserEventArgs & IBaseEventArgs) {
const eventArgs: CancelableBrowserEventArgs & IBaseEventArgs = Object.assign({}, event, { owner: this });
this.onClosing.emit(eventArgs);
event.cancel = eventArgs.cancel;
if (event.cancel) {
return;
}
4 changes: 2 additions & 2 deletions projects/igniteui-angular/src/lib/drop-down/README.md
Original file line number Diff line number Diff line change
@@ -133,9 +133,9 @@ The following outputs are available in the **igx-drop-down** component:
| Name | Cancelable | Description | Parameters
| :--- | :--- | :--- | :--- |
| `onSelection` | false | Emitted when item selection is changing, before the selection completes. | `{ISelectionEventArgs}` |
| `onOpening` | true | Emitted before the dropdown is opened. |
| `onOpening` | true | Emitted before the dropdown is opened. | `CancelableBrowserEventArgs & IBaseEventArgs` |
| `onOpened` | false | Emitted when a dropdown is being opened. |
| `onClosing` | true | Emitted before the dropdown is closed. |
| `onClosing` | true | Emitted before the dropdown is closed. | `CancelableBrowserEventArgs & IBaseEventArgs` |
| `onClosed` | false | Emitted when a dropdown is being closed. |

***NOTE:*** The using `*igxFor` to virtualize `igx-drop-down-item`s, `onSelection` will emit `newSeleciton` and `oldSelection` as type `{ value: any, index: number }`.
17 changes: 11 additions & 6 deletions projects/igniteui-angular/src/lib/drop-down/drop-down.component.ts
Original file line number Diff line number Diff line change
@@ -23,7 +23,7 @@ import { IgxDropDownBaseDirective } from './drop-down.base';
import { DropDownActionKey, Navigate } from './drop-down.common';
import { IGX_DROPDOWN_BASE, IDropDownBase } from './drop-down.common';
import { ISelectionEventArgs } from './drop-down.common';
import { CancelableEventArgs, CancelableBrowserEventArgs, isIE, IBaseEventArgs } from '../core/utils';
import { CancelableBrowserEventArgs, IBaseEventArgs, isIE } from '../core/utils';
import { IgxSelectionAPIService } from '../core/selection';
import { Subject } from 'rxjs';
import { IgxDropDownItemBaseDirective } from './drop-down-item.base';
@@ -81,7 +81,7 @@ export class IgxDropDownComponent extends IgxDropDownBaseDirective implements ID
* ```
*/
@Output()
public onOpening = new EventEmitter<CancelableEventArgs & IBaseEventArgs>();
public onOpening = new EventEmitter<CancelableBrowserEventArgs & IBaseEventArgs>();

/**
* Emitted after the dropdown is opened
@@ -374,8 +374,11 @@ export class IgxDropDownComponent extends IgxDropDownBaseDirective implements ID
/**
* @hidden @internal
*/
public onToggleOpening(e: CancelableEventArgs) {
this.onOpening.emit(e);
public onToggleOpening(e: CancelableBrowserEventArgs & IBaseEventArgs) {
// do not mutate passed event args
const eventArgs: CancelableBrowserEventArgs & IBaseEventArgs = Object.assign({}, e, { owner: this });
this.onOpening.emit(eventArgs);
e.cancel = eventArgs.cancel;
if (e.cancel) {
return;
}
@@ -405,8 +408,10 @@ export class IgxDropDownComponent extends IgxDropDownBaseDirective implements ID
/**
* @hidden @internal
*/
public onToggleClosing(e: CancelableBrowserEventArgs) {
this.onClosing.emit(e);
public onToggleClosing(e: CancelableBrowserEventArgs & IBaseEventArgs) {
const eventArgs: CancelableBrowserEventArgs & IBaseEventArgs = Object.assign({}, e, { owner: this });
this.onClosing.emit(eventArgs);
e.cancel = eventArgs.cancel;
wnvko marked this conversation as resolved.
Show resolved Hide resolved
if (this.virtDir) {
this._scrollPosition = this.virtDir.scrollPosition;
}