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
Expand Up @@ -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 | `IBaseCancelableBrowserEventArgs` |
| `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 | `IBaseCancelableBrowserEventArgs` |
| `onClosed` | Emitted after the dropdown is closed | false | { event: `Event` } |

### Methods
Expand Down
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
Expand Up @@ -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 { IBaseCancelableBrowserEventArgs } from '../core/utils';

const CSS_CLASS_COMBO = 'igx-combo';
const CSS_CLASS_COMBO_DROPDOWN = 'igx-combo__drop-down';
Expand Down Expand Up @@ -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: IBaseCancelableBrowserEventArgs = {
cancel: false,
owner: mockObj,
};
combo.comboInput = <any>{
nativeElement: {
focus: () => {}
}
};
combo.handleOpening(inputEvent);
const expectedCall: IBaseCancelableBrowserEventArgs = 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: IBaseCancelableBrowserEventArgs) => {
e.cancel = true;
});
combo.handleOpening(inputEvent);
expect(inputEvent.cancel).toEqual(true);
sub.unsubscribe();
inputEvent.cancel = false;

sub = combo.onClosing.subscribe((e: IBaseCancelableBrowserEventArgs) => {
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,
Expand All @@ -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
});
Expand All @@ -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
});
Expand All @@ -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
});
Expand All @@ -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
});
Expand All @@ -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
};
Expand Down Expand Up @@ -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
};
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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
});
Expand All @@ -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
});
Expand All @@ -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
});
Expand Down
35 changes: 19 additions & 16 deletions projects/igniteui-angular/src/lib/combo/combo.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
import { FormsModule, ReactiveFormsModule, ControlValueAccessor, NG_VALUE_ACCESSOR, NgControl, AbstractControl } from '@angular/forms';
import { IgxCheckboxModule } from '../checkbox/checkbox.component';
import { IgxSelectionAPIService } from '../core/selection';
import { cloneArray, CancelableEventArgs, CancelableBrowserEventArgs, IBaseEventArgs } from '../core/utils';
import { cloneArray, IBaseEventArgs, IBaseCancelableBrowserEventArgs, IBaseCancelableEventArgs } from '../core/utils';
import { IgxStringFilteringOperand, IgxBooleanFilteringOperand } from '../data-operations/filtering-condition';
import { FilteringLogic } from '../data-operations/filtering-expression.interface';
import { IgxForOfModule, IForOfState, IgxForOfDirective } from '../directives/for-of/for_of.directive';
Expand Down Expand Up @@ -89,7 +89,7 @@ export interface IComboFilteringOptions {
}

/** Event emitted when an igx-combo's selection is changing */
export interface IComboSelectionChangeEventArgs extends CancelableEventArgs, IBaseEventArgs {
export interface IComboSelectionChangeEventArgs extends IBaseCancelableEventArgs {
/** An array containing the values that are currently selected */
oldSelection: any[];
/** An array containing the values that will be selected after this event */
Expand All @@ -105,7 +105,7 @@ export interface IComboSelectionChangeEventArgs extends CancelableEventArgs, IBa
}

/** Event emitted when the igx-combo's search input changes */
export interface IComboSearchInputEventArgs extends CancelableEventArgs, IBaseEventArgs {
export interface IComboSearchInputEventArgs extends IBaseCancelableEventArgs {
/** The text that has been typed into the search input */
searchText: string;
}
Expand Down Expand Up @@ -453,7 +453,7 @@ export class IgxComboComponent extends DisplayDensityBase implements IgxComboBas
* ```
*/
@Output()
public onOpening = new EventEmitter<CancelableEventArgs & IBaseEventArgs>();
public onOpening = new EventEmitter<IBaseCancelableBrowserEventArgs>();

/**
* Emitted after the dropdown is opened
Expand All @@ -473,7 +473,7 @@ export class IgxComboComponent extends DisplayDensityBase implements IgxComboBas
* ```
*/
@Output()
public onClosing = new EventEmitter<CancelableBrowserEventArgs & IBaseEventArgs>();
public onClosing = new EventEmitter<IBaseCancelableBrowserEventArgs>();

/**
* Emitted after the dropdown is closed
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
});
}

Expand Down Expand Up @@ -1489,6 +1490,7 @@ export class IgxComboComponent extends DisplayDensityBase implements IgxComboBas
added,
removed,
event,
owner: this,
displayText,
cancel: false
};
Expand Down Expand Up @@ -1549,11 +1551,10 @@ export class IgxComboComponent extends DisplayDensityBase implements IgxComboBas
* @hidden
* @internal
*/
public handleOpening(event: CancelableEventArgs) {
this.onOpening.emit(event);
if (event.cancel) {
return;
}
public handleOpening(event: IBaseCancelableBrowserEventArgs) {
const eventArgs: IBaseCancelableBrowserEventArgs = Object.assign({}, event, { owner: this });
this.onOpening.emit(eventArgs);
event.cancel = eventArgs.cancel;
}

/**
Expand All @@ -1576,8 +1577,10 @@ export class IgxComboComponent extends DisplayDensityBase implements IgxComboBas
/**
* @hidden @internal
*/
public handleClosing(event) {
this.onClosing.emit(event);
public handleClosing(event: IBaseCancelableBrowserEventArgs) {
const eventArgs: IBaseCancelableBrowserEventArgs = Object.assign({}, event, { owner: this });
this.onClosing.emit(eventArgs);
event.cancel = eventArgs.cancel;
if (event.cancel) {
return;
}
Expand Down
4 changes: 4 additions & 0 deletions projects/igniteui-angular/src/lib/core/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,10 @@ export interface CancelableBrowserEventArgs extends CancelableEventArgs {
event?: Event;
}

export interface IBaseCancelableBrowserEventArgs extends CancelableBrowserEventArgs, IBaseEventArgs {}

export interface IBaseCancelableEventArgs extends CancelableEventArgs, IBaseEventArgs {}

export const HORIZONTAL_NAV_KEYS = new Set(['arrowleft', 'left', 'arrowright', 'right', 'home', 'end']);

export const NAVIGATION_KEYS = new Set([
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ import {
} from './date-picker.utils';
import { DatePickerDisplayValuePipe, DatePickerInputValuePipe } from './date-picker.pipes';
import { IDatePicker } from './date-picker.common';
import { KEYS, CancelableBrowserEventArgs, isIE, isEqual, IBaseEventArgs, mkenum } from '../core/utils';
import { KEYS, isIE, isEqual, IBaseEventArgs, mkenum, IBaseCancelableBrowserEventArgs } from '../core/utils';
import { IgxDatePickerTemplateDirective, IgxDatePickerActionsDirective } from './date-picker.directives';
import { IgxCalendarContainerComponent } from './calendar-container.component';
import { InteractionMode } from '../core/enums';
Expand Down Expand Up @@ -605,7 +605,7 @@ export class IgxDatePickerComponent implements IDatePicker, ControlValueAccessor
* Emitted when the `IgxDatePickerComponent` is being closed.
*/
@Output()
public onClosing = new EventEmitter<CancelableBrowserEventArgs & IBaseEventArgs>();
public onClosing = new EventEmitter<IBaseCancelableBrowserEventArgs>();

/**
* Emitted when selection is made in the calendar.
Expand Down
4 changes: 2 additions & 2 deletions projects/igniteui-angular/src/lib/date-range-picker/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,9 +122,9 @@ With projected inputs:
| Name | Type | Description |
|:-----------------|:----------------------|:------------|
| rangeSelected | IgxDateRangePickerComponent | Emitted when a full range was selected in the `IgxDateRangePickerComponent`. |
| onOpening | CancelableBrowserEventArgs & IBaseEventArgs | Emitted when the calendar starts opening, cancelable. |
| onOpening | IBaseCancelableBrowserEventArgs | Emitted when the calendar starts opening, cancelable. |
| onOpened | IBaseEventArgs | Emitted when the `IgxDateRangePickerComponent` is opened. |
| onClosing | CancelableBrowserEventArgs & IBaseEventArgs | Emitted when the calendar starts closing, cancelable. |
| onClosing | IBaseCancelableBrowserEventArgs | Emitted when the calendar starts closing, cancelable. |
| onClosed | IBaseEventArgs | Emitted when the `IgxDateRangePickerComponent` is closed. |

### Methods
Expand Down
Loading